diff --git a/crypto/aes/_asm/gcm/go.mod b/crypto/aes/_asm/gcm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/aes/_asm/gcm/go.sum b/crypto/aes/_asm/gcm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/aes/_asm/standard/go.mod b/crypto/aes/_asm/standard/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/aes/_asm/standard/go.sum b/crypto/aes/_asm/standard/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/aes/aes.go b/crypto/aes/aes.go new file mode 100644 index 00000000000..23c0a1d08e0 --- /dev/null +++ b/crypto/aes/aes.go @@ -0,0 +1,49 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package aes implements AES encryption (formerly Rijndael), as defined in +// U.S. Federal Information Processing Standards Publication 197. +// +// The AES operations in this package are not implemented using constant-time algorithms. +// An exception is when running on systems with enabled hardware support for AES +// that makes these operations constant-time. Examples include amd64 systems using AES-NI +// extensions and s390x systems using Message-Security-Assist extensions. +// On such systems, when the result of NewCipher is passed to cipher.NewGCM, +// the GHASH operation used by GCM is also constant-time. +package aes + +import ( + "strconv" + + "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" +) + +// The AES block size in bytes. +const BlockSize = 16 + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) +} + +// NewCipher creates and returns a new [cipher.Block]. +// The key argument must be the AES key, +// either 16, 24, or 32 bytes to select +// AES-128, AES-192, or AES-256. +func NewCipher(key []byte) (cipher.Block, error) { + k := len(key) + switch k { + default: + return nil, KeySizeError(k) + case 16, 24, 32: + break + } + if boring.Enabled { + return boring.NewAESCipher(key) + } + return aes.New(key) +} diff --git a/crypto/aes/aes_gcm.go b/crypto/aes/aes_gcm.go deleted file mode 100644 index ae0788438f5..00000000000 --- a/crypto/aes/aes_gcm.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (amd64 || arm64) && !purego - -package aes - -import ( - "errors" - - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/crypto/subtle" -) - -// The following functions are defined in gcm_*.s. - -//go:noescape -func gcmAesInit(productTable *[256]byte, ks []uint32) - -//go:noescape -func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte) - -//go:noescape -func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) - -//go:noescape -func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) - -//go:noescape -func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64) - -const ( - gcmBlockSize = 16 - gcmTagSize = 16 - gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. - gcmStandardNonceSize = 12 -) - -var errOpen = errors.New("cipher: message authentication failed") - -// Assert that aesCipherGCM implements the gcmAble interface. -var _ gcmAble = (*aesCipherGCM)(nil) - -// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only -// called by [crypto/cipher.NewGCM] via the gcmAble interface. -func (c *aesCipherGCM) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { - g := &gcmAsm{ks: c.enc[:c.l], nonceSize: nonceSize, tagSize: tagSize} - gcmAesInit(&g.productTable, g.ks) - return g, nil -} - -type gcmAsm struct { - // ks is the key schedule, the length of which depends on the size of - // the AES key. - ks []uint32 - // productTable contains pre-computed multiples of the binary-field - // element used in GHASH. - productTable [256]byte - // nonceSize contains the expected size of the nonce, in bytes. - nonceSize int - // tagSize contains the size of the tag, in bytes. - tagSize int -} - -func (g *gcmAsm) NonceSize() int { - return g.nonceSize -} - -func (g *gcmAsm) Overhead() int { - return g.tagSize -} - -// sliceForAppend takes a slice and a requested number of bytes. It returns a -// slice with the contents of the given slice followed by that many bytes and a -// second slice that aliases into it and contains only the extra bytes. If the -// original slice has sufficient capacity then no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for -// details. -func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("crypto/cipher: message too large for GCM") - } - - var counter, tagMask [gcmBlockSize]byte - - if len(nonce) == gcmStandardNonceSize { - // Init counter to nonce||1 - copy(counter[:], nonce) - counter[gcmBlockSize-1] = 1 - } else { - // Otherwise counter = GHASH(nonce) - gcmAesData(&g.productTable, nonce, &counter) - gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) - } - - encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) - - var tagOut [gcmTagSize]byte - gcmAesData(&g.productTable, data, &tagOut) - - ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) - if alias.InexactOverlap(out[:len(plaintext)], plaintext) { - panic("crypto/cipher: invalid buffer overlap") - } - if len(plaintext) > 0 { - gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks) - } - gcmAesFinish(&g.productTable, &tagMask, &tagOut, uint64(len(plaintext)), uint64(len(data))) - copy(out[len(plaintext):], tagOut[:]) - - return ret -} - -// Open authenticates and decrypts ciphertext. See the [cipher.AEAD] interface -// for details. -func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - // Sanity check to prevent the authentication from always succeeding if an implementation - // leaves tagSize uninitialized, for example. - if g.tagSize < gcmMinimumTagSize { - panic("crypto/cipher: incorrect GCM tag size") - } - - if len(ciphertext) < g.tagSize { - return nil, errOpen - } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { - return nil, errOpen - } - - tag := ciphertext[len(ciphertext)-g.tagSize:] - ciphertext = ciphertext[:len(ciphertext)-g.tagSize] - - // See GCM spec, section 7.1. - var counter, tagMask [gcmBlockSize]byte - - if len(nonce) == gcmStandardNonceSize { - // Init counter to nonce||1 - copy(counter[:], nonce) - counter[gcmBlockSize-1] = 1 - } else { - // Otherwise counter = GHASH(nonce) - gcmAesData(&g.productTable, nonce, &counter) - gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) - } - - encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) - - var expectedTag [gcmTagSize]byte - gcmAesData(&g.productTable, data, &expectedTag) - - ret, out := sliceForAppend(dst, len(ciphertext)) - if alias.InexactOverlap(out, ciphertext) { - panic("crypto/cipher: invalid buffer overlap") - } - if len(ciphertext) > 0 { - gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks) - } - gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data))) - - if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { - clear(out) - return nil, errOpen - } - - return ret, nil -} diff --git a/crypto/aes/aes_test.go b/crypto/aes/aes_test.go index efb9f541e1b..9acf57a006e 100644 --- a/crypto/aes/aes_test.go +++ b/crypto/aes/aes_test.go @@ -6,242 +6,15 @@ package aes import ( "fmt" - "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" "testing" -) - -// See const.go for overview of math here. - -// Test that powx is initialized correctly. -// (Can adapt this code to generate it too.) -func TestPowx(t *testing.T) { - p := 1 - for i := 0; i < len(powx); i++ { - if powx[i] != byte(p) { - t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p) - } - p <<= 1 - if p&0x100 != 0 { - p ^= poly - } - } -} - -// Multiply b and c as GF(2) polynomials modulo poly -func mul(b, c uint32) uint32 { - i := b - j := c - s := uint32(0) - for k := uint32(1); k < 0x100 && j != 0; k <<= 1 { - // Invariant: k == 1<>8 - } - } -} -// Test that decryption tables are correct. -// (Can adapt this code to generate them too.) -func TestTd(t *testing.T) { - for i := 0; i < 256; i++ { - s := uint32(sbox1[i]) - s9 := mul(s, 0x9) - sb := mul(s, 0xb) - sd := mul(s, 0xd) - se := mul(s, 0xe) - w := se<<24 | s9<<16 | sd<<8 | sb - td := [][256]uint32{td0, td1, td2, td3} - for j := 0; j < 4; j++ { - if x := td[j][i]; x != w { - t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w) - } - w = w<<24 | w>>8 - } - } -} + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" +) // Test vectors are from FIPS 197: // https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf -// Appendix A of FIPS 197: Key expansion examples -type KeyTest struct { - key []byte - enc []uint32 - dec []uint32 // decryption expansion; not in FIPS 197, computed from C implementation. -} - -var keyTests = []KeyTest{ - { - // A.1. Expansion of a 128-bit Cipher Key - []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, - []uint32{ - 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, - 0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605, - 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, - 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, - 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, - 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, - 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, - 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, - 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, - 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, - 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, - }, - []uint32{ - 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, - 0xc7b5a63, 0x1319eafe, 0xb0398890, 0x664cfbb4, - 0xdf7d925a, 0x1f62b09d, 0xa320626e, 0xd6757324, - 0x12c07647, 0xc01f22c7, 0xbc42d2f3, 0x7555114a, - 0x6efcd876, 0xd2df5480, 0x7c5df034, 0xc917c3b9, - 0x6ea30afc, 0xbc238cf6, 0xae82a4b4, 0xb54a338d, - 0x90884413, 0xd280860a, 0x12a12842, 0x1bc89739, - 0x7c1f13f7, 0x4208c219, 0xc021ae48, 0x969bf7b, - 0xcc7505eb, 0x3e17d1ee, 0x82296c51, 0xc9481133, - 0x2b3708a7, 0xf262d405, 0xbc3ebdbf, 0x4b617d62, - 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x9cf4f3c, - }, - }, - { - // A.2. Expansion of a 192-bit Cipher Key - []byte{ - 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, - 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, - }, - []uint32{ - 0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5, - 0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5, - 0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2, - 0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd, - 0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f, - 0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6, - 0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767, - 0xc0a69407, 0xd19da4e1, 0xec1786eb, 0x6fa64971, - 0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3, - 0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e, - 0xa7e1466c, 0x9411f1df, 0x821f750a, 0xad07d753, - 0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5, - 0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202, - }, - nil, - }, - { - // A.3. Expansion of a 256-bit Cipher Key - []byte{ - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, - }, - []uint32{ - 0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781, - 0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4, - 0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde, - 0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a, - 0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96, - 0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3, - 0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464, - 0x98c5bfc9, 0xbebd198e, 0x268c3ba7, 0x09e04214, - 0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80, - 0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239, - 0xde136967, 0x6ccc5a71, 0xfa256395, 0x9674ee15, - 0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3, - 0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a, - 0xcafaaae3, 0xe4d59b34, 0x9adf6ace, 0xbd10190d, - 0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e, - }, - nil, - }, -} - -// Test key expansion against FIPS 197 examples. -func TestExpandKey(t *testing.T) { -L: - for i, tt := range keyTests { - enc := make([]uint32, len(tt.enc)) - var dec []uint32 - if tt.dec != nil { - dec = make([]uint32, len(tt.dec)) - } - // This test could only test Go version of expandKey because asm - // version might use different memory layout for expanded keys - // This is OK because we don't expose expanded keys to the outside - expandKeyGo(tt.key, enc, dec) - for j, v := range enc { - if v != tt.enc[j] { - t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j]) - continue L - } - } - for j, v := range dec { - if v != tt.dec[j] { - t.Errorf("key %d: dec[%d] = %#x, want %#x", i, j, v, tt.dec[j]) - continue L - } - } - } -} - // Appendix B, C of FIPS 197: Cipher examples, Example vectors. type CryptTest struct { key []byte @@ -282,6 +55,10 @@ var encryptTests = []CryptTest{ // Test Cipher Encrypt method against FIPS 197 examples. func TestCipherEncrypt(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testCipherEncrypt) +} + +func testCipherEncrypt(t *testing.T) { for i, tt := range encryptTests { c, err := NewCipher(tt.key) if err != nil { @@ -301,6 +78,10 @@ func TestCipherEncrypt(t *testing.T) { // Test Cipher Decrypt against FIPS 197 examples. func TestCipherDecrypt(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testCipherDecrypt) +} + +func testCipherDecrypt(t *testing.T) { for i, tt := range encryptTests { c, err := NewCipher(tt.key) if err != nil { @@ -320,6 +101,10 @@ func TestCipherDecrypt(t *testing.T) { // Test AES against the general cipher.Block interface tester func TestAESBlock(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testAESBlock) +} + +func testAESBlock(t *testing.T) { for _, keylen := range []int{128, 192, 256} { t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { cryptotest.TestBlock(t, keylen/8, NewCipher) @@ -327,6 +112,16 @@ func TestAESBlock(t *testing.T) { } } +func TestExtraMethods(t *testing.T) { + if boring.Enabled { + t.Skip("Go+BoringCrypto still uses the interface upgrades in crypto/cipher") + } + cryptotest.TestAllImplementations(t, "aes", func(t *testing.T) { + b, _ := NewCipher(make([]byte, 16)) + cryptotest.NoExtraMethods(t, &b) + }) +} + func BenchmarkEncrypt(b *testing.B) { b.Run("AES-128", func(b *testing.B) { benchmarkEncrypt(b, encryptTests[1]) }) b.Run("AES-192", func(b *testing.B) { benchmarkEncrypt(b, encryptTests[2]) }) @@ -365,20 +160,6 @@ func benchmarkDecrypt(b *testing.B, tt CryptTest) { } } -func BenchmarkExpand(b *testing.B) { - b.Run("AES-128", func(b *testing.B) { benchmarkExpand(b, encryptTests[1]) }) - b.Run("AES-192", func(b *testing.B) { benchmarkExpand(b, encryptTests[2]) }) - b.Run("AES-256", func(b *testing.B) { benchmarkExpand(b, encryptTests[3]) }) -} - -func benchmarkExpand(b *testing.B, tt CryptTest) { - c := &aesCipher{l: uint8(len(tt.key) + 28)} - b.ResetTimer() - for i := 0; i < b.N; i++ { - expandKey(tt.key, c.enc[:c.l], c.dec[:c.l]) - } -} - func BenchmarkCreateCipher(b *testing.B) { b.Run("AES-128", func(b *testing.B) { benchmarkCreateCipher(b, encryptTests[1]) }) b.Run("AES-192", func(b *testing.B) { benchmarkCreateCipher(b, encryptTests[2]) }) diff --git a/crypto/aes/asm_s390x.s b/crypto/aes/asm_s390x.s deleted file mode 100644 index 5da0d8bf9cb..00000000000 --- a/crypto/aes/asm_s390x.s +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -#include "textflag.h" - -// func cryptBlocks(c code, key, dst, src *byte, length int) -TEXT ·cryptBlocks(SB),NOSPLIT,$0-40 - MOVD key+8(FP), R1 - MOVD dst+16(FP), R2 - MOVD src+24(FP), R4 - MOVD length+32(FP), R5 - MOVD c+0(FP), R0 -loop: - KM R2, R4 // cipher message (KM) - BVS loop // branch back if interrupted - XOR R0, R0 - RET - -// func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) -TEXT ·cryptBlocksChain(SB),NOSPLIT,$48-48 - LA params-48(SP), R1 - MOVD iv+8(FP), R8 - MOVD key+16(FP), R9 - MVC $16, 0(R8), 0(R1) // move iv into params - MVC $32, 0(R9), 16(R1) // move key into params - MOVD dst+24(FP), R2 - MOVD src+32(FP), R4 - MOVD length+40(FP), R5 - MOVD c+0(FP), R0 -loop: - KMC R2, R4 // cipher message with chaining (KMC) - BVS loop // branch back if interrupted - XOR R0, R0 - MVC $16, 0(R1), 0(R8) // update iv - RET - -// func xorBytes(dst, a, b []byte) int -TEXT ·xorBytes(SB),NOSPLIT,$0-80 - MOVD dst_base+0(FP), R1 - MOVD a_base+24(FP), R2 - MOVD b_base+48(FP), R3 - MOVD a_len+32(FP), R4 - MOVD b_len+56(FP), R5 - CMPBLE R4, R5, skip - MOVD R5, R4 -skip: - MOVD R4, ret+72(FP) - MOVD $0, R5 - CMPBLT R4, $8, tail -loop: - MOVD 0(R2)(R5*1), R7 - MOVD 0(R3)(R5*1), R8 - XOR R7, R8 - MOVD R8, 0(R1)(R5*1) - LAY 8(R5), R5 - SUB $8, R4 - CMPBGE R4, $8, loop -tail: - CMPBEQ R4, $0, done - MOVB 0(R2)(R5*1), R7 - MOVB 0(R3)(R5*1), R8 - XOR R7, R8 - MOVB R8, 0(R1)(R5*1) - LAY 1(R5), R5 - SUB $1, R4 - BR tail -done: - RET - -// func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *[16]byte) -TEXT ·cryptBlocksGCM(SB),NOSPLIT,$0-112 - MOVD src_len+64(FP), R0 - MOVD buf_base+80(FP), R1 - MOVD cnt+104(FP), R12 - LMG (R12), R2, R3 - - // Check that the src size is less than or equal to the buffer size. - MOVD buf_len+88(FP), R4 - CMP R0, R4 - BGT crash - - // Check that the src size is a multiple of 16-bytes. - MOVD R0, R4 - AND $0xf, R4 - BLT crash // non-zero - - // Check that the src size is less than or equal to the dst size. - MOVD dst_len+40(FP), R4 - CMP R0, R4 - BGT crash - - MOVD R2, R4 - MOVD R2, R6 - MOVD R2, R8 - MOVD R3, R5 - MOVD R3, R7 - MOVD R3, R9 - ADDW $1, R5 - ADDW $2, R7 - ADDW $3, R9 -incr: - CMP R0, $64 - BLT tail - STMG R2, R9, (R1) - ADDW $4, R3 - ADDW $4, R5 - ADDW $4, R7 - ADDW $4, R9 - MOVD $64(R1), R1 - SUB $64, R0 - BR incr -tail: - CMP R0, $0 - BEQ crypt - STMG R2, R3, (R1) - ADDW $1, R3 - MOVD $16(R1), R1 - SUB $16, R0 - BR tail -crypt: - STMG R2, R3, (R12) // update next counter value - MOVD fn+0(FP), R0 // function code (encryption) - MOVD key_base+8(FP), R1 // key - MOVD buf_base+80(FP), R2 // counter values - MOVD dst_base+32(FP), R4 // dst - MOVD src_base+56(FP), R6 // src - MOVD src_len+64(FP), R7 // len -loop: - KMCTR R4, R2, R6 // cipher message with counter (KMCTR) - BVS loop // branch back if interrupted - RET -crash: - MOVD $0, (R0) - RET - -// func ghash(key *gcmHashKey, hash *[16]byte, data []byte) -TEXT ·ghash(SB),NOSPLIT,$32-40 - MOVD $65, R0 // GHASH function code - MOVD key+0(FP), R2 - LMG (R2), R6, R7 - MOVD hash+8(FP), R8 - LMG (R8), R4, R5 - MOVD $params-32(SP), R1 - STMG R4, R7, (R1) - LMG data+16(FP), R2, R3 // R2=base, R3=len -loop: - KIMD R0, R2 // compute intermediate message digest (KIMD) - BVS loop // branch back if interrupted - MVC $16, (R1), (R8) - MOVD $0, R0 - RET - -// func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) -TEXT ·kmaGCM(SB),NOSPLIT,$112-120 - MOVD fn+0(FP), R0 - MOVD $params-112(SP), R1 - - // load ptr/len pairs - LMG dst+32(FP), R2, R3 // R2=base R3=len - LMG src+56(FP), R4, R5 // R4=base R5=len - LMG aad+80(FP), R6, R7 // R6=base R7=len - - // setup parameters - MOVD cnt+112(FP), R8 - XC $12, (R1), (R1) // reserved - MVC $4, 12(R8), 12(R1) // set chain value - MVC $16, (R8), 64(R1) // set initial counter value - XC $32, 16(R1), 16(R1) // set hash subkey and tag - SLD $3, R7, R12 - MOVD R12, 48(R1) // set total AAD length - SLD $3, R5, R12 - MOVD R12, 56(R1) // set total plaintext/ciphertext length - - LMG key+8(FP), R8, R9 // R8=base R9=len - MVC $16, (R8), 80(R1) // set key - CMPBEQ R9, $16, kma - MVC $8, 16(R8), 96(R1) - CMPBEQ R9, $24, kma - MVC $8, 24(R8), 104(R1) - -kma: - KMA R2, R6, R4 // Cipher Message with Authentication - BVS kma - - MOVD tag+104(FP), R2 - MVC $16, 16(R1), 0(R2) // copy tag to output - MOVD cnt+112(FP), R8 - MVC $4, 12(R1), 12(R8) // update counter value - - RET diff --git a/crypto/aes/cbc_ppc64x.go b/crypto/aes/cbc_ppc64x.go deleted file mode 100644 index 0ec39143bf8..00000000000 --- a/crypto/aes/cbc_ppc64x.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (ppc64 || ppc64le) && !purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" -) - -// Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces. -var _ cbcEncAble = (*aesCipherAsm)(nil) -var _ cbcDecAble = (*aesCipherAsm)(nil) - -const cbcEncrypt = 1 -const cbcDecrypt = 0 - -type cbc struct { - b *aesCipherAsm - enc int - iv [BlockSize]byte -} - -func (b *aesCipherAsm) NewCBCEncrypter(iv []byte) cipher.BlockMode { - var c cbc - c.b = b - c.enc = cbcEncrypt - copy(c.iv[:], iv) - return &c -} - -func (b *aesCipherAsm) NewCBCDecrypter(iv []byte) cipher.BlockMode { - var c cbc - c.b = b - c.enc = cbcDecrypt - copy(c.iv[:], iv) - return &c -} - -func (x *cbc) BlockSize() int { return BlockSize } - -// cryptBlocksChain invokes the cipher message identifying encrypt or decrypt. -// -//go:noescape -func cryptBlocksChain(src, dst *byte, length int, key *uint32, iv *byte, enc int, nr int) - -func (x *cbc) CryptBlocks(dst, src []byte) { - if len(src)%BlockSize != 0 { - panic("crypto/cipher: input not full blocks") - } - if len(dst) < len(src) { - panic("crypto/cipher: output smaller than input") - } - if alias.InexactOverlap(dst[:len(src)], src) { - panic("crypto/cipher: invalid buffer overlap") - } - if len(src) > 0 { - if x.enc == cbcEncrypt { - cryptBlocksChain(&src[0], &dst[0], len(src), &x.b.enc[0], &x.iv[0], x.enc, int(x.b.l)/4-1) - } else { - cryptBlocksChain(&src[0], &dst[0], len(src), &x.b.dec[0], &x.iv[0], x.enc, int(x.b.l)/4-1) - } - } -} - -func (x *cbc) SetIV(iv []byte) { - if len(iv) != BlockSize { - panic("cipher: incorrect length IV") - } - copy(x.iv[:], iv) -} diff --git a/crypto/aes/cbc_s390x.go b/crypto/aes/cbc_s390x.go deleted file mode 100644 index 04fbb60496f..00000000000 --- a/crypto/aes/cbc_s390x.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" -) - -// Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces. -var _ cbcEncAble = (*aesCipherAsm)(nil) -var _ cbcDecAble = (*aesCipherAsm)(nil) - -type cbc struct { - b *aesCipherAsm - c code - iv [BlockSize]byte -} - -func (b *aesCipherAsm) NewCBCEncrypter(iv []byte) cipher.BlockMode { - var c cbc - c.b = b - c.c = b.function - copy(c.iv[:], iv) - return &c -} - -func (b *aesCipherAsm) NewCBCDecrypter(iv []byte) cipher.BlockMode { - var c cbc - c.b = b - c.c = b.function + 128 // decrypt function code is encrypt + 128 - copy(c.iv[:], iv) - return &c -} - -func (x *cbc) BlockSize() int { return BlockSize } - -// cryptBlocksChain invokes the cipher message with chaining (KMC) instruction -// with the given function code. The length must be a multiple of BlockSize (16). -// -//go:noescape -func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) - -func (x *cbc) CryptBlocks(dst, src []byte) { - if len(src)%BlockSize != 0 { - panic("crypto/cipher: input not full blocks") - } - if len(dst) < len(src) { - panic("crypto/cipher: output smaller than input") - } - if alias.InexactOverlap(dst[:len(src)], src) { - panic("crypto/cipher: invalid buffer overlap") - } - if len(src) > 0 { - cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src)) - } -} - -func (x *cbc) SetIV(iv []byte) { - if len(iv) != BlockSize { - panic("cipher: incorrect length IV") - } - copy(x.iv[:], iv) -} diff --git a/crypto/aes/cipher.go b/crypto/aes/cipher.go deleted file mode 100644 index fb4cf3116ed..00000000000 --- a/crypto/aes/cipher.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package aes - -import ( - "strconv" - - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/crypto/internal/boring" -) - -// The AES block size in bytes. -const BlockSize = 16 - -// A cipher is an instance of AES encryption using a particular key. -type aesCipher struct { - l uint8 // only this length of the enc and dec array is actually used - enc [28 + 32]uint32 - dec [28 + 32]uint32 -} - -type KeySizeError int - -func (k KeySizeError) Error() string { - return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) -} - -// NewCipher creates and returns a new [cipher.Block]. -// The key argument should be the AES key, -// either 16, 24, or 32 bytes to select -// AES-128, AES-192, or AES-256. -func NewCipher(key []byte) (cipher.Block, error) { - k := len(key) - switch k { - default: - return nil, KeySizeError(k) - case 16, 24, 32: - break - } - if boring.Enabled { - return boring.NewAESCipher(key) - } - return newCipher(key) -} - -// newCipherGeneric creates and returns a new cipher.Block -// implemented in pure Go. -func newCipherGeneric(key []byte) (cipher.Block, error) { - c := aesCipher{l: uint8(len(key) + 28)} - expandKeyGo(key, c.enc[:c.l], c.dec[:c.l]) - return &c, nil -} - -func (c *aesCipher) BlockSize() int { return BlockSize } - -func (c *aesCipher) Encrypt(dst, src []byte) { - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - encryptBlockGo(c.enc[:c.l], dst, src) -} - -func (c *aesCipher) Decrypt(dst, src []byte) { - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - decryptBlockGo(c.dec[:c.l], dst, src) -} diff --git a/crypto/aes/cipher_asm.go b/crypto/aes/cipher_asm.go deleted file mode 100644 index e2b14b77c17..00000000000 --- a/crypto/aes/cipher_asm.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (amd64 || arm64 || ppc64 || ppc64le) && !purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/crypto/internal/boring" - "github.com/runZeroInc/excrypto/internal/cpu" - "github.com/runZeroInc/excrypto/internal/goarch" -) - -// defined in asm_*.s - -//go:noescape -func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) - -//go:noescape -func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) - -//go:noescape -func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) - -type aesCipherAsm struct { - aesCipher -} - -// aesCipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM -// will use the optimised implementation in aes_gcm.go when possible. -// Instances of this type only exist when hasGCMAsm returns true. Likewise, -// the gcmAble implementation is in aes_gcm.go. -type aesCipherGCM struct { - aesCipherAsm -} - -var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasAES || goarch.IsPpc64 == 1 || goarch.IsPpc64le == 1 -var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL - -func newCipher(key []byte) (cipher.Block, error) { - if !supportsAES { - return newCipherGeneric(key) - } - // Note that under certain circumstances, we only return the inner aesCipherAsm. - // This avoids an unnecessary allocation of the aesCipher struct. - c := aesCipherGCM{aesCipherAsm{aesCipher{l: uint8(len(key) + 28)}}} - var rounds int - switch len(key) { - case 128 / 8: - rounds = 10 - case 192 / 8: - rounds = 12 - case 256 / 8: - rounds = 14 - default: - return nil, KeySizeError(len(key)) - } - - expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) - if supportsAES && supportsGFMUL { - return &c, nil - } - return &c.aesCipherAsm, nil -} - -func (c *aesCipherAsm) BlockSize() int { return BlockSize } - -func (c *aesCipherAsm) Encrypt(dst, src []byte) { - boring.Unreachable() - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - encryptBlockAsm(int(c.l)/4-1, &c.enc[0], &dst[0], &src[0]) -} - -func (c *aesCipherAsm) Decrypt(dst, src []byte) { - boring.Unreachable() - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - decryptBlockAsm(int(c.l)/4-1, &c.dec[0], &dst[0], &src[0]) -} - -// expandKey is used by BenchmarkExpand to ensure that the asm implementation -// of key expansion is used for the benchmark when it is available. -func expandKey(key []byte, enc, dec []uint32) { - if supportsAES { - rounds := 10 // rounds needed for AES128 - switch len(key) { - case 192 / 8: - rounds = 12 - case 256 / 8: - rounds = 14 - } - expandKeyAsm(rounds, &key[0], &enc[0], &dec[0]) - } else { - expandKeyGo(key, enc, dec) - } -} diff --git a/crypto/aes/cipher_generic.go b/crypto/aes/cipher_generic.go deleted file mode 100644 index 79e49d846ff..00000000000 --- a/crypto/aes/cipher_generic.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (!amd64 && !s390x && !ppc64 && !ppc64le && !arm64) || purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" -) - -// newCipher calls the newCipherGeneric function -// directly. Platforms with hardware accelerated -// implementations of AES should implement their -// own version of newCipher (which may then call -// newCipherGeneric if needed). -func newCipher(key []byte) (cipher.Block, error) { - return newCipherGeneric(key) -} - -// expandKey is used by BenchmarkExpand and should -// call an assembly implementation if one is available. -func expandKey(key []byte, enc, dec []uint32) { - expandKeyGo(key, enc, dec) -} diff --git a/crypto/aes/cipher_s390x.go b/crypto/aes/cipher_s390x.go deleted file mode 100644 index a1a6f6c0f2b..00000000000 --- a/crypto/aes/cipher_s390x.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/internal/cpu" -) - -type code int - -// Function codes for the cipher message family of instructions. -const ( - aes128 code = 18 - aes192 = 19 - aes256 = 20 -) - -type aesCipherAsm struct { - function code // code for cipher message instruction - key []byte // key (128, 192 or 256 bits) - storage [32]byte // array backing key slice -} - -// cryptBlocks invokes the cipher message (KM) instruction with -// the given function code. This is equivalent to AES in ECB -// mode. The length must be a multiple of BlockSize (16). -// -//go:noescape -func cryptBlocks(c code, key, dst, src *byte, length int) - -func newCipher(key []byte) (cipher.Block, error) { - // The aesCipherAsm type implements the cbcEncAble, cbcDecAble, - // ctrAble and gcmAble interfaces. We therefore need to check - // for all the features required to implement these modes. - // Keep in sync with crypto/tls/common.go. - if !(cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)) { - return newCipherGeneric(key) - } - - var function code - switch len(key) { - case 128 / 8: - function = aes128 - case 192 / 8: - function = aes192 - case 256 / 8: - function = aes256 - default: - return nil, KeySizeError(len(key)) - } - - var c aesCipherAsm - c.function = function - c.key = c.storage[:len(key)] - copy(c.key, key) - return &c, nil -} - -func (c *aesCipherAsm) BlockSize() int { return BlockSize } - -func (c *aesCipherAsm) Encrypt(dst, src []byte) { - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) -} - -func (c *aesCipherAsm) Decrypt(dst, src []byte) { - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } - if len(dst) < BlockSize { - panic("crypto/aes: output not full block") - } - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } - // The decrypt function code is equal to the function code + 128. - cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) -} - -// expandKey is used by BenchmarkExpand. cipher message (KM) does not need key -// expansion so there is no assembly equivalent. -func expandKey(key []byte, enc, dec []uint32) { - expandKeyGo(key, enc, dec) -} diff --git a/crypto/aes/ctr_s390x.go b/crypto/aes/ctr_s390x.go deleted file mode 100644 index 49f6ecba47d..00000000000 --- a/crypto/aes/ctr_s390x.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/internal/byteorder" -) - -// Assert that aesCipherAsm implements the ctrAble interface. -var _ ctrAble = (*aesCipherAsm)(nil) - -// xorBytes xors the contents of a and b and places the resulting values into -// dst. If a and b are not the same length then the number of bytes processed -// will be equal to the length of shorter of the two. Returns the number -// of bytes processed. -// -//go:noescape -func xorBytes(dst, a, b []byte) int - -// streamBufferSize is the number of bytes of encrypted counter values to cache. -const streamBufferSize = 32 * BlockSize - -type aesctr struct { - block *aesCipherAsm // block cipher - ctr [2]uint64 // next value of the counter (big endian) - buffer []byte // buffer for the encrypted counter values - storage [streamBufferSize]byte // array backing buffer slice -} - -// NewCTR returns a Stream which encrypts/decrypts using the AES block -// cipher in counter mode. The length of iv must be the same as [BlockSize]. -func (c *aesCipherAsm) NewCTR(iv []byte) cipher.Stream { - if len(iv) != BlockSize { - panic("cipher.NewCTR: IV length must equal block size") - } - var ac aesctr - ac.block = c - ac.ctr[0] = byteorder.BeUint64(iv[0:]) // high bits - ac.ctr[1] = byteorder.BeUint64(iv[8:]) // low bits - ac.buffer = ac.storage[:0] - return &ac -} - -func (c *aesctr) refill() { - // Fill up the buffer with an incrementing count. - c.buffer = c.storage[:streamBufferSize] - c0, c1 := c.ctr[0], c.ctr[1] - for i := 0; i < streamBufferSize; i += 16 { - byteorder.BePutUint64(c.buffer[i+0:], c0) - byteorder.BePutUint64(c.buffer[i+8:], c1) - - // Increment in big endian: c0 is high, c1 is low. - c1++ - if c1 == 0 { - // add carry - c0++ - } - } - c.ctr[0], c.ctr[1] = c0, c1 - // Encrypt the buffer using AES in ECB mode. - cryptBlocks(c.block.function, &c.block.key[0], &c.buffer[0], &c.buffer[0], streamBufferSize) -} - -func (c *aesctr) XORKeyStream(dst, src []byte) { - if len(dst) < len(src) { - panic("crypto/cipher: output smaller than input") - } - if alias.InexactOverlap(dst[:len(src)], src) { - panic("crypto/cipher: invalid buffer overlap") - } - for len(src) > 0 { - if len(c.buffer) == 0 { - c.refill() - } - n := xorBytes(dst, src, c.buffer) - c.buffer = c.buffer[n:] - src = src[n:] - dst = dst[n:] - } -} diff --git a/crypto/aes/gcm_ppc64x.go b/crypto/aes/gcm_ppc64x.go deleted file mode 100644 index e7125a0f9a1..00000000000 --- a/crypto/aes/gcm_ppc64x.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (ppc64le || ppc64) && !purego - -package aes - -import ( - "errors" - "runtime" - - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/crypto/subtle" - "github.com/runZeroInc/excrypto/internal/byteorder" -) - -// This file implements GCM using an optimized GHASH function. - -//go:noescape -func gcmInit(productTable *[256]byte, h []byte) - -//go:noescape -func gcmHash(output []byte, productTable *[256]byte, inp []byte, len int) - -//go:noescape -func gcmMul(output []byte, productTable *[256]byte) - -const ( - gcmCounterSize = 16 - gcmBlockSize = 16 - gcmTagSize = 16 - gcmStandardNonceSize = 12 -) - -var errOpen = errors.New("cipher: message authentication failed") - -// Assert that aesCipherGCM implements the gcmAble interface. -var _ gcmAble = (*aesCipherAsm)(nil) - -type gcmAsm struct { - cipher *aesCipherAsm - // ks is the key schedule, the length of which depends on the size of - // the AES key. - ks []uint32 - // productTable contains pre-computed multiples of the binary-field - // element used in GHASH. - productTable [256]byte - // nonceSize contains the expected size of the nonce, in bytes. - nonceSize int - // tagSize contains the size of the tag, in bytes. - tagSize int -} - -func counterCryptASM(nr int, out, in []byte, counter *[gcmBlockSize]byte, key *uint32) - -// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only -// called by [crypto/cipher.NewGCM] via the gcmAble interface. -func (c *aesCipherAsm) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { - var h1, h2 uint64 - g := &gcmAsm{cipher: c, ks: c.enc[:c.l], nonceSize: nonceSize, tagSize: tagSize} - - hle := make([]byte, gcmBlockSize) - - c.Encrypt(hle, hle) - - // Reverse the bytes in each 8 byte chunk - // Load little endian, store big endian - if runtime.GOARCH == "ppc64le" { - h1 = byteorder.LeUint64(hle[:8]) - h2 = byteorder.LeUint64(hle[8:]) - } else { - h1 = byteorder.BeUint64(hle[:8]) - h2 = byteorder.BeUint64(hle[8:]) - } - byteorder.BePutUint64(hle[:8], h1) - byteorder.BePutUint64(hle[8:], h2) - gcmInit(&g.productTable, hle) - - return g, nil -} - -func (g *gcmAsm) NonceSize() int { - return g.nonceSize -} - -func (g *gcmAsm) Overhead() int { - return g.tagSize -} - -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// deriveCounter computes the initial GCM counter state from the given nonce. -func (g *gcmAsm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) { - if len(nonce) == gcmStandardNonceSize { - copy(counter[:], nonce) - counter[gcmBlockSize-1] = 1 - } else { - var hash [16]byte - g.paddedGHASH(&hash, nonce) - lens := gcmLengths(0, uint64(len(nonce))*8) - g.paddedGHASH(&hash, lens[:]) - copy(counter[:], hash[:]) - } -} - -// counterCrypt encrypts in using AES in counter mode and places the result -// into out. counter is the initial count value and will be updated with the next -// count value. The length of out must be greater than or equal to the length -// of in. -// counterCryptASM implements counterCrypt which then allows the loop to -// be unrolled and optimized. -func (g *gcmAsm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { - counterCryptASM(int(g.cipher.l)/4-1, out, in, counter, &g.cipher.enc[0]) - -} - -// increments the rightmost 32-bits of the count value by 1. -func gcmInc32(counterBlock *[16]byte) { - c := counterBlock[len(counterBlock)-4:] - x := byteorder.BeUint32(c) + 1 - byteorder.BePutUint32(c, x) -} - -// paddedGHASH pads data with zeroes until its length is a multiple of -// 16-bytes. It then calculates a new value for hash using the ghash -// algorithm. -func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) { - if siz := len(data) - (len(data) % gcmBlockSize); siz > 0 { - gcmHash(hash[:], &g.productTable, data[:], siz) - data = data[siz:] - } - if len(data) > 0 { - var s [16]byte - copy(s[:], data) - gcmHash(hash[:], &g.productTable, s[:], len(s)) - } -} - -// auth calculates GHASH(ciphertext, additionalData), masks the result with -// tagMask and writes the result to out. -func (g *gcmAsm) auth(out, ciphertext, aad []byte, tagMask *[gcmTagSize]byte) { - var hash [16]byte - g.paddedGHASH(&hash, aad) - g.paddedGHASH(&hash, ciphertext) - lens := gcmLengths(uint64(len(aad))*8, uint64(len(ciphertext))*8) - g.paddedGHASH(&hash, lens[:]) - - copy(out, hash[:]) - for i := range out { - out[i] ^= tagMask[i] - } -} - -// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for -// details. -func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { - if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") - } - if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("cipher: message too large for GCM") - } - - ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) - if alias.InexactOverlap(out[:len(plaintext)], plaintext) { - panic("crypto/cipher: invalid buffer overlap") - } - - var counter, tagMask [gcmBlockSize]byte - g.deriveCounter(&counter, nonce) - - g.cipher.Encrypt(tagMask[:], counter[:]) - gcmInc32(&counter) - - g.counterCrypt(out, plaintext, &counter) - g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask) - - return ret -} - -// Open authenticates and decrypts ciphertext. See the [cipher.AEAD] interface -// for details. -func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") - } - if len(ciphertext) < g.tagSize { - return nil, errOpen - } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { - return nil, errOpen - } - - tag := ciphertext[len(ciphertext)-g.tagSize:] - ciphertext = ciphertext[:len(ciphertext)-g.tagSize] - - var counter, tagMask [gcmBlockSize]byte - g.deriveCounter(&counter, nonce) - - g.cipher.Encrypt(tagMask[:], counter[:]) - gcmInc32(&counter) - - var expectedTag [gcmTagSize]byte - g.auth(expectedTag[:], ciphertext, data, &tagMask) - - ret, out := sliceForAppend(dst, len(ciphertext)) - if alias.InexactOverlap(out, ciphertext) { - panic("crypto/cipher: invalid buffer overlap") - } - - if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { - clear(out) - return nil, errOpen - } - - g.counterCrypt(out, ciphertext, &counter) - return ret, nil -} - -func gcmLengths(len0, len1 uint64) [16]byte { - return [16]byte{ - byte(len0 >> 56), - byte(len0 >> 48), - byte(len0 >> 40), - byte(len0 >> 32), - byte(len0 >> 24), - byte(len0 >> 16), - byte(len0 >> 8), - byte(len0), - byte(len1 >> 56), - byte(len1 >> 48), - byte(len1 >> 40), - byte(len1 >> 32), - byte(len1 >> 24), - byte(len1 >> 16), - byte(len1 >> 8), - byte(len1), - } -} diff --git a/crypto/aes/gcm_s390x.go b/crypto/aes/gcm_s390x.go deleted file mode 100644 index 752beac892d..00000000000 --- a/crypto/aes/gcm_s390x.go +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package aes - -import ( - "errors" - - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" - "github.com/runZeroInc/excrypto/crypto/subtle" - "github.com/runZeroInc/excrypto/internal/byteorder" - "github.com/runZeroInc/excrypto/internal/cpu" -) - -// This file contains two implementations of AES-GCM. The first implementation -// (gcmAsm) uses the KMCTR instruction to encrypt using AES in counter mode and -// the KIMD instruction for GHASH. The second implementation (gcmKMA) uses the -// newer KMA instruction which performs both operations. - -// gcmCount represents a 16-byte big-endian count value. -type gcmCount [16]byte - -// inc increments the rightmost 32-bits of the count value by 1. -func (x *gcmCount) inc() { - byteorder.BePutUint32(x[len(x)-4:], byteorder.BeUint32(x[len(x)-4:])+1) -} - -// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array. -func gcmLengths(len0, len1 uint64) [16]byte { - v := [16]byte{} - byteorder.BePutUint64(v[0:], len0) - byteorder.BePutUint64(v[8:], len1) - return v -} - -// gcmHashKey represents the 16-byte hash key required by the GHASH algorithm. -type gcmHashKey [16]byte - -type gcmAsm struct { - block *aesCipherAsm - hashKey gcmHashKey - nonceSize int - tagSize int -} - -const ( - gcmBlockSize = 16 - gcmTagSize = 16 - gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. - gcmStandardNonceSize = 12 -) - -var errOpen = errors.New("cipher: message authentication failed") - -// Assert that aesCipherAsm implements the gcmAble interface. -var _ gcmAble = (*aesCipherAsm)(nil) - -// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only -// called by [crypto/cipher.NewGCM] via the gcmAble interface. -func (c *aesCipherAsm) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { - var hk gcmHashKey - c.Encrypt(hk[:], hk[:]) - g := gcmAsm{ - block: c, - hashKey: hk, - nonceSize: nonceSize, - tagSize: tagSize, - } - if cpu.S390X.HasAESGCM { - g := gcmKMA{g} - return &g, nil - } - return &g, nil -} - -func (g *gcmAsm) NonceSize() int { - return g.nonceSize -} - -func (g *gcmAsm) Overhead() int { - return g.tagSize -} - -// sliceForAppend takes a slice and a requested number of bytes. It returns a -// slice with the contents of the given slice followed by that many bytes and a -// second slice that aliases into it and contains only the extra bytes. If the -// original slice has sufficient capacity then no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// ghash uses the GHASH algorithm to hash data with the given key. The initial -// hash value is given by hash which will be updated with the new hash value. -// The length of data must be a multiple of 16-bytes. -// -//go:noescape -func ghash(key *gcmHashKey, hash *[16]byte, data []byte) - -// paddedGHASH pads data with zeroes until its length is a multiple of -// 16-bytes. It then calculates a new value for hash using the GHASH algorithm. -func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) { - siz := len(data) &^ 0xf // align size to 16-bytes - if siz > 0 { - ghash(&g.hashKey, hash, data[:siz]) - data = data[siz:] - } - if len(data) > 0 { - var s [16]byte - copy(s[:], data) - ghash(&g.hashKey, hash, s[:]) - } -} - -// cryptBlocksGCM encrypts src using AES in counter mode using the given -// function code and key. The rightmost 32-bits of the counter are incremented -// between each block as required by the GCM spec. The initial counter value -// is given by cnt, which is updated with the value of the next counter value -// to use. -// -// The lengths of both dst and buf must be greater than or equal to the length -// of src. buf may be partially or completely overwritten during the execution -// of the function. -// -//go:noescape -func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *gcmCount) - -// counterCrypt encrypts src using AES in counter mode and places the result -// into dst. cnt is the initial count value and will be updated with the next -// count value. The length of dst must be greater than or equal to the length -// of src. -func (g *gcmAsm) counterCrypt(dst, src []byte, cnt *gcmCount) { - // Copying src into a buffer improves performance on some models when - // src and dst point to the same underlying array. We also need a - // buffer for counter values. - var ctrbuf, srcbuf [2048]byte - for len(src) >= 16 { - siz := len(src) - if len(src) > len(ctrbuf) { - siz = len(ctrbuf) - } - siz &^= 0xf // align siz to 16-bytes - copy(srcbuf[:], src[:siz]) - cryptBlocksGCM(g.block.function, g.block.key, dst[:siz], srcbuf[:siz], ctrbuf[:], cnt) - src = src[siz:] - dst = dst[siz:] - } - if len(src) > 0 { - var x [16]byte - g.block.Encrypt(x[:], cnt[:]) - for i := range src { - dst[i] = src[i] ^ x[i] - } - cnt.inc() - } -} - -// deriveCounter computes the initial GCM counter state from the given nonce. -// See NIST SP 800-38D, section 7.1. -func (g *gcmAsm) deriveCounter(nonce []byte) gcmCount { - // GCM has two modes of operation with respect to the initial counter - // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" - // for nonces of other lengths. For a 96-bit nonce, the nonce, along - // with a four-byte big-endian counter starting at one, is used - // directly as the starting counter. For other nonce sizes, the counter - // is computed by passing it through the GHASH function. - var counter gcmCount - if len(nonce) == gcmStandardNonceSize { - copy(counter[:], nonce) - counter[gcmBlockSize-1] = 1 - } else { - var hash [16]byte - g.paddedGHASH(&hash, nonce) - lens := gcmLengths(0, uint64(len(nonce))*8) - g.paddedGHASH(&hash, lens[:]) - copy(counter[:], hash[:]) - } - return counter -} - -// auth calculates GHASH(ciphertext, additionalData), masks the result with -// tagMask and writes the result to out. -func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { - var hash [16]byte - g.paddedGHASH(&hash, additionalData) - g.paddedGHASH(&hash, ciphertext) - lens := gcmLengths(uint64(len(additionalData))*8, uint64(len(ciphertext))*8) - g.paddedGHASH(&hash, lens[:]) - - copy(out, hash[:]) - for i := range out { - out[i] ^= tagMask[i] - } -} - -// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for -// details. -func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("crypto/cipher: message too large for GCM") - } - - ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) - if alias.InexactOverlap(out[:len(plaintext)], plaintext) { - panic("crypto/cipher: invalid buffer overlap") - } - - counter := g.deriveCounter(nonce) - - var tagMask [gcmBlockSize]byte - g.block.Encrypt(tagMask[:], counter[:]) - counter.inc() - - var tagOut [gcmTagSize]byte - g.counterCrypt(out, plaintext, &counter) - g.auth(tagOut[:], out[:len(plaintext)], data, &tagMask) - copy(out[len(plaintext):], tagOut[:]) - - return ret -} - -// Open authenticates and decrypts ciphertext. See the [cipher.AEAD] interface -// for details. -func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - // Sanity check to prevent the authentication from always succeeding if an implementation - // leaves tagSize uninitialized, for example. - if g.tagSize < gcmMinimumTagSize { - panic("crypto/cipher: incorrect GCM tag size") - } - if len(ciphertext) < g.tagSize { - return nil, errOpen - } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { - return nil, errOpen - } - - tag := ciphertext[len(ciphertext)-g.tagSize:] - ciphertext = ciphertext[:len(ciphertext)-g.tagSize] - - counter := g.deriveCounter(nonce) - - var tagMask [gcmBlockSize]byte - g.block.Encrypt(tagMask[:], counter[:]) - counter.inc() - - var expectedTag [gcmTagSize]byte - g.auth(expectedTag[:], ciphertext, data, &tagMask) - - ret, out := sliceForAppend(dst, len(ciphertext)) - if alias.InexactOverlap(out, ciphertext) { - panic("crypto/cipher: invalid buffer overlap") - } - - if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { - // The AESNI code decrypts and authenticates concurrently, and - // so overwrites dst in the event of a tag mismatch. That - // behavior is mimicked here in order to be consistent across - // platforms. - clear(out) - return nil, errOpen - } - - g.counterCrypt(out, ciphertext, &counter) - return ret, nil -} - -// gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should -// only be used if hasKMA is true. -type gcmKMA struct { - gcmAsm -} - -// flags for the KMA instruction -const ( - kmaHS = 1 << 10 // hash subkey supplied - kmaLAAD = 1 << 9 // last series of additional authenticated data - kmaLPC = 1 << 8 // last series of plaintext or ciphertext blocks - kmaDecrypt = 1 << 7 // decrypt -) - -// kmaGCM executes the encryption or decryption operation given by fn. The tag -// will be calculated and written to tag. cnt should contain the current -// counter state and will be overwritten with the updated counter state. -// TODO(mundaym): could pass in hash subkey -// -//go:noescape -func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) - -// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for -// details. -func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("crypto/cipher: message too large for GCM") - } - - ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) - if alias.InexactOverlap(out[:len(plaintext)], plaintext) { - panic("crypto/cipher: invalid buffer overlap") - } - - counter := g.deriveCounter(nonce) - fc := g.block.function | kmaLAAD | kmaLPC - - var tag [gcmTagSize]byte - kmaGCM(fc, g.block.key, out[:len(plaintext)], plaintext, data, &tag, &counter) - copy(out[len(plaintext):], tag[:]) - - return ret -} - -// Open authenticates and decrypts ciphertext. See the [cipher.AEAD] interface -// for details. -func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(nonce) != g.nonceSize { - panic("crypto/cipher: incorrect nonce length given to GCM") - } - if len(ciphertext) < g.tagSize { - return nil, errOpen - } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { - return nil, errOpen - } - - tag := ciphertext[len(ciphertext)-g.tagSize:] - ciphertext = ciphertext[:len(ciphertext)-g.tagSize] - ret, out := sliceForAppend(dst, len(ciphertext)) - if alias.InexactOverlap(out, ciphertext) { - panic("crypto/cipher: invalid buffer overlap") - } - - if g.tagSize < gcmMinimumTagSize { - panic("crypto/cipher: incorrect GCM tag size") - } - - counter := g.deriveCounter(nonce) - fc := g.block.function | kmaLAAD | kmaLPC | kmaDecrypt - - var expectedTag [gcmTagSize]byte - kmaGCM(fc, g.block.key, out[:len(ciphertext)], ciphertext, data, &expectedTag, &counter) - - if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { - // The AESNI code decrypts and authenticates concurrently, and - // so overwrites dst in the event of a tag mismatch. That - // behavior is mimicked here in order to be consistent across - // platforms. - clear(out) - return nil, errOpen - } - - return ret, nil -} diff --git a/crypto/aes/modes.go b/crypto/aes/modes.go deleted file mode 100644 index c48fc7aaf76..00000000000 --- a/crypto/aes/modes.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" -) - -// gcmAble is implemented by cipher.Blocks that can provide an optimized -// implementation of GCM through the AEAD interface. -// See crypto/cipher/gcm.go. -type gcmAble interface { - NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) -} - -// cbcEncAble is implemented by cipher.Blocks that can provide an optimized -// implementation of CBC encryption through the cipher.BlockMode interface. -// See crypto/cipher/cbc.go. -type cbcEncAble interface { - NewCBCEncrypter(iv []byte) cipher.BlockMode -} - -// cbcDecAble is implemented by cipher.Blocks that can provide an optimized -// implementation of CBC decryption through the cipher.BlockMode interface. -// See crypto/cipher/cbc.go. -type cbcDecAble interface { - NewCBCDecrypter(iv []byte) cipher.BlockMode -} - -// ctrAble is implemented by cipher.Blocks that can provide an optimized -// implementation of CTR through the cipher.Stream interface. -// See crypto/cipher/ctr.go. -type ctrAble interface { - NewCTR(iv []byte) cipher.Stream -} diff --git a/crypto/aes/modes_test.go b/crypto/aes/modes_test.go deleted file mode 100644 index e0726049d32..00000000000 --- a/crypto/aes/modes_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package aes - -import ( - "github.com/runZeroInc/excrypto/crypto/cipher" - "testing" -) - -// Check that the optimized implementations of cipher modes will -// be picked up correctly. - -// testInterface can be asserted to check that a type originates -// from this test group. -type testInterface interface { - InAESPackage() bool -} - -// testBlock implements the cipher.Block interface and any *Able -// interfaces that need to be tested. -type testBlock struct{} - -func (*testBlock) BlockSize() int { return 0 } -func (*testBlock) Encrypt(a, b []byte) {} -func (*testBlock) Decrypt(a, b []byte) {} -func (*testBlock) NewGCM(int, int) (cipher.AEAD, error) { - return &testAEAD{}, nil -} -func (*testBlock) NewCBCEncrypter([]byte) cipher.BlockMode { - return &testBlockMode{} -} -func (*testBlock) NewCBCDecrypter([]byte) cipher.BlockMode { - return &testBlockMode{} -} -func (*testBlock) NewCTR([]byte) cipher.Stream { - return &testStream{} -} - -// testAEAD implements the cipher.AEAD interface. -type testAEAD struct{} - -func (*testAEAD) NonceSize() int { return 0 } -func (*testAEAD) Overhead() int { return 0 } -func (*testAEAD) Seal(a, b, c, d []byte) []byte { return []byte{} } -func (*testAEAD) Open(a, b, c, d []byte) ([]byte, error) { return []byte{}, nil } -func (*testAEAD) InAESPackage() bool { return true } - -// Test the gcmAble interface is detected correctly by the cipher package. -func TestGCMAble(t *testing.T) { - b := cipher.Block(&testBlock{}) - if _, ok := b.(gcmAble); !ok { - t.Fatalf("testBlock does not implement the gcmAble interface") - } - aead, err := cipher.NewGCM(b) - if err != nil { - t.Fatalf("%v", err) - } - if _, ok := aead.(testInterface); !ok { - t.Fatalf("cipher.NewGCM did not use gcmAble interface") - } -} - -// testBlockMode implements the cipher.BlockMode interface. -type testBlockMode struct{} - -func (*testBlockMode) BlockSize() int { return 0 } -func (*testBlockMode) CryptBlocks(a, b []byte) {} -func (*testBlockMode) InAESPackage() bool { return true } - -// Test the cbcEncAble interface is detected correctly by the cipher package. -func TestCBCEncAble(t *testing.T) { - b := cipher.Block(&testBlock{}) - if _, ok := b.(cbcEncAble); !ok { - t.Fatalf("testBlock does not implement the cbcEncAble interface") - } - bm := cipher.NewCBCEncrypter(b, []byte{}) - if _, ok := bm.(testInterface); !ok { - t.Fatalf("cipher.NewCBCEncrypter did not use cbcEncAble interface") - } -} - -// Test the cbcDecAble interface is detected correctly by the cipher package. -func TestCBCDecAble(t *testing.T) { - b := cipher.Block(&testBlock{}) - if _, ok := b.(cbcDecAble); !ok { - t.Fatalf("testBlock does not implement the cbcDecAble interface") - } - bm := cipher.NewCBCDecrypter(b, []byte{}) - if _, ok := bm.(testInterface); !ok { - t.Fatalf("cipher.NewCBCDecrypter did not use cbcDecAble interface") - } -} - -// testStream implements the cipher.Stream interface. -type testStream struct{} - -func (*testStream) XORKeyStream(a, b []byte) {} -func (*testStream) InAESPackage() bool { return true } - -// Test the ctrAble interface is detected correctly by the cipher package. -func TestCTRAble(t *testing.T) { - b := cipher.Block(&testBlock{}) - if _, ok := b.(ctrAble); !ok { - t.Fatalf("testBlock does not implement the ctrAble interface") - } - s := cipher.NewCTR(b, []byte{}) - if _, ok := s.(testInterface); !ok { - t.Fatalf("cipher.NewCTR did not use ctrAble interface") - } -} diff --git a/crypto/boring/boring.go b/crypto/boring/boring.go new file mode 100644 index 00000000000..c72af2bce60 --- /dev/null +++ b/crypto/boring/boring.go @@ -0,0 +1,21 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +// Package boring exposes functions that are only available when building with +// Go+BoringCrypto. This package is available on all targets as long as the +// Go+BoringCrypto toolchain is used. Use the Enabled function to determine +// whether the BoringCrypto core is actually in use. +// +// Any time the Go+BoringCrypto toolchain is used, the "boringcrypto" build tag +// is satisfied, so that applications can tag files that use this package. +package boring + +import "github.com/runZeroInc/excrypto/crypto/internal/boring" + +// Enabled reports whether BoringCrypto handles supported crypto operations. +func Enabled() bool { + return boring.Enabled +} diff --git a/crypto/boring/boring_test.go b/crypto/boring/boring_test.go new file mode 100644 index 00000000000..054a2ce43dc --- /dev/null +++ b/crypto/boring/boring_test.go @@ -0,0 +1,23 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +package boring_test + +import ( + "runtime" + "testing" + + "github.com/runZeroInc/excrypto/crypto/boring" +) + +func TestEnabled(t *testing.T) { + supportedPlatform := runtime.GOOS == "linux" && (runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64") + if supportedPlatform && !boring.Enabled() { + t.Error("Enabled returned false on a supported platform") + } else if !supportedPlatform && boring.Enabled() { + t.Error("Enabled returned true on an unsupported platform") + } +} diff --git a/crypto/boring/notboring.go b/crypto/boring/notboring.go deleted file mode 100644 index b960ce6a83f..00000000000 --- a/crypto/boring/notboring.go +++ /dev/null @@ -1,8 +0,0 @@ -package boring - -// boringcrypto is disabled in this fork -var Enabled bool - -func Unreachable() { - -} diff --git a/crypto/boring/notboring_test.go b/crypto/boring/notboring_test.go new file mode 100644 index 00000000000..07016284649 --- /dev/null +++ b/crypto/boring/notboring_test.go @@ -0,0 +1,13 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (goexperiment.boringcrypto && !boringcrypto) || (!goexperiment.boringcrypto && boringcrypto) + +package boring_test + +import "testing" + +func TestNotBoring(t *testing.T) { + t.Error("goexperiment.boringcrypto and boringcrypto should be equivalent build tags") +} diff --git a/crypto/cipher/benchmark_test.go b/crypto/cipher/benchmark_test.go index 533966e0322..fec1b354b69 100644 --- a/crypto/cipher/benchmark_test.go +++ b/crypto/cipher/benchmark_test.go @@ -5,10 +5,11 @@ package cipher_test import ( - "github.com/runZeroInc/excrypto/crypto/aes" - "github.com/runZeroInc/excrypto/crypto/cipher" "strconv" "testing" + + "github.com/runZeroInc/excrypto/crypto/aes" + "github.com/runZeroInc/excrypto/crypto/cipher" ) func benchmarkAESGCMSeal(b *testing.B, buf []byte, keySize int) { @@ -86,28 +87,16 @@ func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Str const almost1K = 1024 - 5 const almost8K = 8*1024 - 5 -func BenchmarkAESCFBEncrypt1K(b *testing.B) { - benchmarkAESStream(b, cipher.NewCFBEncrypter, make([]byte, almost1K)) -} - -func BenchmarkAESCFBDecrypt1K(b *testing.B) { - benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost1K)) -} - -func BenchmarkAESCFBDecrypt8K(b *testing.B) { - benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost8K)) -} - -func BenchmarkAESOFB1K(b *testing.B) { - benchmarkAESStream(b, cipher.NewOFB, make([]byte, almost1K)) -} - -func BenchmarkAESCTR1K(b *testing.B) { - benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K)) -} - -func BenchmarkAESCTR8K(b *testing.B) { - benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K)) +func BenchmarkAESCTR(b *testing.B) { + b.Run("50", func(b *testing.B) { + benchmarkAESStream(b, cipher.NewCTR, make([]byte, 50)) + }) + b.Run("1K", func(b *testing.B) { + benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K)) + }) + b.Run("8K", func(b *testing.B) { + benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K)) + }) } func BenchmarkAESCBCEncrypt1K(b *testing.B) { diff --git a/crypto/cipher/cbc.go b/crypto/cipher/cbc.go index 6bc78c1f95d..5fc35e96790 100644 --- a/crypto/cipher/cbc.go +++ b/crypto/cipher/cbc.go @@ -14,7 +14,9 @@ package cipher import ( "bytes" - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -37,9 +39,8 @@ func newCBC(b Block, iv []byte) *cbc { type cbcEncrypter cbc // cbcEncAble is an interface implemented by ciphers that have a specific -// optimized implementation of CBC encryption, like crypto/aes. -// NewCBCEncrypter will check for this interface and return the specific -// BlockMode if found. +// optimized implementation of CBC encryption. crypto/aes doesn't use this +// anymore, and we'd like to eventually remove it. type cbcEncAble interface { NewCBCEncrypter(iv []byte) BlockMode } @@ -51,6 +52,12 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { if len(iv) != b.BlockSize() { panic("cipher.NewCBCEncrypter: IV length must equal block size") } + if b, ok := b.(*aes.Block); ok { + return aes.NewCBCEncrypter(b, [16]byte(iv)) + } + if fips140only.Enabled { + panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") + } if cbc, ok := b.(cbcEncAble); ok { return cbc.NewCBCEncrypter(iv) } @@ -80,6 +87,9 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { if alias.InexactOverlap(dst[:len(src)], src) { panic("crypto/cipher: invalid buffer overlap") } + if _, ok := x.b.(*aes.Block); ok { + panic("crypto/cipher: internal error: generic CBC used with AES") + } iv := x.iv @@ -108,9 +118,8 @@ func (x *cbcEncrypter) SetIV(iv []byte) { type cbcDecrypter cbc // cbcDecAble is an interface implemented by ciphers that have a specific -// optimized implementation of CBC decryption, like crypto/aes. -// NewCBCDecrypter will check for this interface and return the specific -// BlockMode if found. +// optimized implementation of CBC decryption. crypto/aes doesn't use this +// anymore, and we'd like to eventually remove it. type cbcDecAble interface { NewCBCDecrypter(iv []byte) BlockMode } @@ -122,6 +131,12 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { if len(iv) != b.BlockSize() { panic("cipher.NewCBCDecrypter: IV length must equal block size") } + if b, ok := b.(*aes.Block); ok { + return aes.NewCBCDecrypter(b, [16]byte(iv)) + } + if fips140only.Enabled { + panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") + } if cbc, ok := b.(cbcDecAble); ok { return cbc.NewCBCDecrypter(iv) } @@ -151,6 +166,9 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { if alias.InexactOverlap(dst[:len(src)], src) { panic("crypto/cipher: invalid buffer overlap") } + if _, ok := x.b.(*aes.Block); ok { + panic("crypto/cipher: internal error: generic CBC used with AES") + } if len(src) == 0 { return } diff --git a/crypto/cipher/cbc_aes_test.go b/crypto/cipher/cbc_aes_test.go index 0d98a50d158..f45e8a12a2f 100644 --- a/crypto/cipher/cbc_aes_test.go +++ b/crypto/cipher/cbc_aes_test.go @@ -12,9 +12,11 @@ package cipher_test import ( "bytes" + "testing" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" - "testing" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" ) var cbcAESTests = []struct { @@ -64,6 +66,10 @@ var cbcAESTests = []struct { } func TestCBCEncrypterAES(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testCBCEncrypterAES) +} + +func testCBCEncrypterAES(t *testing.T) { for _, test := range cbcAESTests { c, err := aes.NewCipher(test.key) if err != nil { @@ -84,6 +90,10 @@ func TestCBCEncrypterAES(t *testing.T) { } func TestCBCDecrypterAES(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testCBCDecrypterAES) +} + +func testCBCDecrypterAES(t *testing.T) { for _, test := range cbcAESTests { c, err := aes.NewCipher(test.key) if err != nil { diff --git a/crypto/cipher/cbc_test.go b/crypto/cipher/cbc_test.go index 532c3ccd0c0..75f189638eb 100644 --- a/crypto/cipher/cbc_test.go +++ b/crypto/cipher/cbc_test.go @@ -6,34 +6,36 @@ package cipher_test import ( "fmt" - "github.com/runZeroInc/excrypto/crypto/aes" - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/des" - "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" "io" "math/rand" "testing" "time" + + "github.com/runZeroInc/excrypto/crypto/aes" + "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/des" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" ) // Test CBC Blockmode against the general cipher.BlockMode interface tester func TestCBCBlockMode(t *testing.T) { - for _, keylen := range []int{128, 192, 256} { - - t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { - rng := newRandReader(t) + cryptotest.TestAllImplementations(t, "aes", func(t *testing.T) { + for _, keylen := range []int{128, 192, 256} { + t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { + rng := newRandReader(t) - key := make([]byte, keylen/8) - rng.Read(key) + key := make([]byte, keylen/8) + rng.Read(key) - block, err := aes.NewCipher(key) - if err != nil { - panic(err) - } + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } - cryptotest.TestBlockMode(t, block, cipher.NewCBCEncrypter, cipher.NewCBCDecrypter) - }) - } + cryptotest.TestBlockMode(t, block, cipher.NewCBCEncrypter, cipher.NewCBCDecrypter) + }) + } + }) t.Run("DES", func(t *testing.T) { rng := newRandReader(t) @@ -50,6 +52,16 @@ func TestCBCBlockMode(t *testing.T) { }) } +func TestCBCExtraMethods(t *testing.T) { + block, _ := aes.NewCipher(make([]byte, 16)) + iv := make([]byte, block.BlockSize()) + s := cipher.NewCBCEncrypter(block, iv) + cryptotest.NoExtraMethods(t, &s, "SetIV") + + s = cipher.NewCBCDecrypter(block, iv) + cryptotest.NoExtraMethods(t, &s, "SetIV") +} + func newRandReader(t *testing.T) io.Reader { seed := time.Now().UnixNano() t.Logf("Deterministic RNG seed: 0x%x", seed) diff --git a/crypto/cipher/cfb.go b/crypto/cipher/cfb.go index eaf629ca4cd..b9bf0735be5 100644 --- a/crypto/cipher/cfb.go +++ b/crypto/cipher/cfb.go @@ -7,7 +7,8 @@ package cipher import ( - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -53,21 +54,39 @@ func (x *cfb) XORKeyStream(dst, src []byte) { // NewCFBEncrypter returns a [Stream] which encrypts with cipher feedback mode, // using the given [Block]. The iv must be the same length as the [Block]'s block // size. +// +// Deprecated: CFB mode is not authenticated, which generally enables active +// attacks to manipulate and recover the plaintext. It is recommended that +// applications use [AEAD] modes instead. The standard library implementation of +// CFB is also unoptimized and not validated as part of the FIPS 140-3 module. +// If an unauthenticated [Stream] mode is required, use [NewCTR] instead. func NewCFBEncrypter(block Block, iv []byte) Stream { + if fips140only.Enabled { + panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode") + } return newCFB(block, iv, false) } // NewCFBDecrypter returns a [Stream] which decrypts with cipher feedback mode, // using the given [Block]. The iv must be the same length as the [Block]'s block // size. +// +// Deprecated: CFB mode is not authenticated, which generally enables active +// attacks to manipulate and recover the plaintext. It is recommended that +// applications use [AEAD] modes instead. The standard library implementation of +// CFB is also unoptimized and not validated as part of the FIPS 140-3 module. +// If an unauthenticated [Stream] mode is required, use [NewCTR] instead. func NewCFBDecrypter(block Block, iv []byte) Stream { + if fips140only.Enabled { + panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode") + } return newCFB(block, iv, true) } func newCFB(block Block, iv []byte, decrypt bool) Stream { blockSize := block.BlockSize() if len(iv) != blockSize { - // stack trace will indicate whether it was de or encryption + // Stack trace will indicate whether it was de- or en-cryption. panic("cipher.newCFB: IV length must equal block size") } x := &cfb{ diff --git a/crypto/cipher/cipher.go b/crypto/cipher/cipher.go index df6f596b4d0..4d631991ee1 100644 --- a/crypto/cipher/cipher.go +++ b/crypto/cipher/cipher.go @@ -59,3 +59,40 @@ type BlockMode interface { // maintains state and does not reset at each CryptBlocks call. CryptBlocks(dst, src []byte) } + +// AEAD is a cipher mode providing authenticated encryption with associated +// data. For a description of the methodology, see +// https://en.wikipedia.org/wiki/Authenticated_encryption. +type AEAD interface { + // NonceSize returns the size of the nonce that must be passed to Seal + // and Open. + NonceSize() int + + // Overhead returns the maximum difference between the lengths of a + // plaintext and its ciphertext. + Overhead() int + + // Seal encrypts and authenticates plaintext, authenticates the + // additional data and appends the result to dst, returning the updated + // slice. The nonce must be NonceSize() bytes long and unique for all + // time, for a given key. + // + // To reuse plaintext's storage for the encrypted output, use plaintext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. + // dst and additionalData may not overlap. + Seal(dst, nonce, plaintext, additionalData []byte) []byte + + // Open decrypts and authenticates ciphertext, authenticates the + // additional data and, if successful, appends the resulting plaintext + // to dst, returning the updated slice. The nonce must be NonceSize() + // bytes long and both it and the additional data must match the + // value passed to Seal. + // + // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap ciphertext. + // dst and additionalData may not overlap. + // + // Even if the function fails, the contents of dst, up to its capacity, + // may be overwritten. + Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) +} diff --git a/crypto/cipher/cipher_test.go b/crypto/cipher/cipher_test.go deleted file mode 100644 index 65ea0016f28..00000000000 --- a/crypto/cipher/cipher_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cipher_test - -import ( - "bytes" - "testing" - - "github.com/runZeroInc/excrypto/crypto/aes" - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/des" -) - -func TestCryptBlocks(t *testing.T) { - buf := make([]byte, 16) - block, _ := aes.NewCipher(buf) - - mode := cipher.NewCBCDecrypter(block, buf) - mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) - mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) - - mode = cipher.NewCBCEncrypter(block, buf) - mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) - mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) -} - -func mustPanic(t *testing.T, msg string, f func()) { - defer func() { - err := recover() - if err == nil { - t.Errorf("function did not panic, wanted %q", msg) - } else if err != msg { - t.Errorf("got panic %v, wanted %q", err, msg) - } - }() - f() -} - -func TestEmptyPlaintext(t *testing.T) { - var key [16]byte - a, err := aes.NewCipher(key[:16]) - if err != nil { - t.Fatal(err) - } - d, err := des.NewCipher(key[:8]) - if err != nil { - t.Fatal(err) - } - - s := 16 - pt := make([]byte, s) - ct := make([]byte, s) - for i := 0; i < 16; i++ { - pt[i], ct[i] = byte(i), byte(i) - } - - assertEqual := func(name string, got, want []byte) { - if !bytes.Equal(got, want) { - t.Fatalf("%s: got %v, want %v", name, got, want) - } - } - - for _, b := range []cipher.Block{a, d} { - iv := make([]byte, b.BlockSize()) - cbce := cipher.NewCBCEncrypter(b, iv) - cbce.CryptBlocks(ct, pt[:0]) - assertEqual("CBC encrypt", ct, pt) - - cbcd := cipher.NewCBCDecrypter(b, iv) - cbcd.CryptBlocks(ct, pt[:0]) - assertEqual("CBC decrypt", ct, pt) - - cfbe := cipher.NewCFBEncrypter(b, iv) - cfbe.XORKeyStream(ct, pt[:0]) - assertEqual("CFB encrypt", ct, pt) - - cfbd := cipher.NewCFBDecrypter(b, iv) - cfbd.XORKeyStream(ct, pt[:0]) - assertEqual("CFB decrypt", ct, pt) - - ctr := cipher.NewCTR(b, iv) - ctr.XORKeyStream(ct, pt[:0]) - assertEqual("CTR", ct, pt) - - ofb := cipher.NewOFB(b, iv) - ofb.XORKeyStream(ct, pt[:0]) - assertEqual("OFB", ct, pt) - } -} diff --git a/crypto/cipher/ctr.go b/crypto/cipher/ctr.go index 4b6e0890d2a..293883ebfef 100644 --- a/crypto/cipher/ctr.go +++ b/crypto/cipher/ctr.go @@ -15,7 +15,9 @@ package cipher import ( "bytes" - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -29,8 +31,8 @@ type ctr struct { const streamBufferSize = 512 // ctrAble is an interface implemented by ciphers that have a specific optimized -// implementation of CTR, like crypto/aes. NewCTR will check for this interface -// and return the specific Stream if found. +// implementation of CTR. crypto/aes doesn't use this anymore, and we'd like to +// eventually remove it. type ctrAble interface { NewCTR(iv []byte) Stream } @@ -38,6 +40,12 @@ type ctrAble interface { // NewCTR returns a [Stream] which encrypts/decrypts using the given [Block] in // counter mode. The length of iv must be the same as the [Block]'s block size. func NewCTR(block Block, iv []byte) Stream { + if block, ok := block.(*aes.Block); ok { + return aesCtrWrapper{aes.NewCTR(block, iv)} + } + if fips140only.Enabled { + panic("crypto/cipher: use of CTR with non-AES ciphers is not allowed in FIPS 140-only mode") + } if ctr, ok := block.(ctrAble); ok { return ctr.NewCTR(iv) } @@ -56,6 +64,15 @@ func NewCTR(block Block, iv []byte) Stream { } } +// aesCtrWrapper hides extra methods from aes.CTR. +type aesCtrWrapper struct { + c *aes.CTR +} + +func (x aesCtrWrapper) XORKeyStream(dst, src []byte) { + x.c.XORKeyStream(dst, src) +} + func (x *ctr) refill() { remain := len(x.out) - x.outUsed copy(x.out, x.out[x.outUsed:]) @@ -84,6 +101,9 @@ func (x *ctr) XORKeyStream(dst, src []byte) { if alias.InexactOverlap(dst[:len(src)], src) { panic("crypto/cipher: invalid buffer overlap") } + if _, ok := x.b.(*aes.Block); ok { + panic("crypto/cipher: internal error: generic CTR used with AES") + } for len(src) > 0 { if x.outUsed >= len(x.out)-x.b.BlockSize() { x.refill() diff --git a/crypto/cipher/ctr_aes_test.go b/crypto/cipher/ctr_aes_test.go index 472ad9cc6e4..cf3ac0024bd 100644 --- a/crypto/cipher/ctr_aes_test.go +++ b/crypto/cipher/ctr_aes_test.go @@ -12,9 +12,18 @@ package cipher_test import ( "bytes" + "encoding/hex" + "fmt" + "math/rand" + "sort" + "strings" + "testing" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" - "testing" + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" + fipsaes "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" ) var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff} @@ -66,6 +75,10 @@ var ctrAESTests = []struct { } func TestCTR_AES(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", testCTR_AES) +} + +func testCTR_AES(t *testing.T) { for _, tt := range ctrAESTests { test := tt.name @@ -100,3 +113,194 @@ func TestCTR_AES(t *testing.T) { } } } + +func makeTestingCiphers(aesBlock cipher.Block, iv []byte) (genericCtr, multiblockCtr cipher.Stream) { + return cipher.NewCTR(wrap(aesBlock), iv), cipher.NewCTR(aesBlock, iv) +} + +func randBytes(t *testing.T, r *rand.Rand, count int) []byte { + t.Helper() + buf := make([]byte, count) + n, err := r.Read(buf) + if err != nil { + t.Fatal(err) + } + if n != count { + t.Fatal("short read from Rand") + } + return buf +} + +const aesBlockSize = 16 + +type ctrAble interface { + NewCTR(iv []byte) cipher.Stream +} + +// Verify that multiblock AES CTR (src/crypto/aes/ctr_*.s) +// produces the same results as generic single-block implementation. +// This test runs checks on random IV. +func TestCTR_AES_multiblock_random_IV(t *testing.T) { + r := rand.New(rand.NewSource(54321)) + iv := randBytes(t, r, aesBlockSize) + const Size = 100 + + for _, keySize := range []int{16, 24, 32} { + keySize := keySize + t.Run(fmt.Sprintf("keySize=%d", keySize), func(t *testing.T) { + key := randBytes(t, r, keySize) + aesBlock, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + genericCtr, _ := makeTestingCiphers(aesBlock, iv) + + plaintext := randBytes(t, r, Size) + + // Generate reference ciphertext. + genericCiphertext := make([]byte, len(plaintext)) + genericCtr.XORKeyStream(genericCiphertext, plaintext) + + // Split the text in 3 parts in all possible ways and encrypt them + // individually using multiblock implementation to catch edge cases. + + for part1 := 0; part1 <= Size; part1++ { + part1 := part1 + t.Run(fmt.Sprintf("part1=%d", part1), func(t *testing.T) { + for part2 := 0; part2 <= Size-part1; part2++ { + part2 := part2 + t.Run(fmt.Sprintf("part2=%d", part2), func(t *testing.T) { + _, multiblockCtr := makeTestingCiphers(aesBlock, iv) + multiblockCiphertext := make([]byte, len(plaintext)) + multiblockCtr.XORKeyStream(multiblockCiphertext[:part1], plaintext[:part1]) + multiblockCtr.XORKeyStream(multiblockCiphertext[part1:part1+part2], plaintext[part1:part1+part2]) + multiblockCtr.XORKeyStream(multiblockCiphertext[part1+part2:], plaintext[part1+part2:]) + if !bytes.Equal(genericCiphertext, multiblockCiphertext) { + t.Fatal("multiblock CTR's output does not match generic CTR's output") + } + }) + } + }) + } + }) + } +} + +func parseHex(str string) []byte { + b, err := hex.DecodeString(strings.ReplaceAll(str, " ", "")) + if err != nil { + panic(err) + } + return b +} + +// Verify that multiblock AES CTR (src/crypto/aes/ctr_*.s) +// produces the same results as generic single-block implementation. +// This test runs checks on edge cases (IV overflows). +func TestCTR_AES_multiblock_overflow_IV(t *testing.T) { + r := rand.New(rand.NewSource(987654)) + + const Size = 4096 + plaintext := randBytes(t, r, Size) + + ivs := [][]byte{ + parseHex("00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF"), + parseHex("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF"), + parseHex("FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00"), + parseHex("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF fe"), + parseHex("00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF fe"), + parseHex("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00"), + parseHex("00 00 00 00 00 00 00 01 FF FF FF FF FF FF FF 00"), + parseHex("00 00 00 00 00 00 00 01 FF FF FF FF FF FF FF FF"), + parseHex("00 00 00 00 00 00 00 01 FF FF FF FF FF FF FF fe"), + parseHex("00 00 00 00 00 00 00 01 FF FF FF FF FF FF FF 00"), + } + + for _, keySize := range []int{16, 24, 32} { + keySize := keySize + t.Run(fmt.Sprintf("keySize=%d", keySize), func(t *testing.T) { + for _, iv := range ivs { + key := randBytes(t, r, keySize) + aesBlock, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + + t.Run(fmt.Sprintf("iv=%s", hex.EncodeToString(iv)), func(t *testing.T) { + for _, offset := range []int{0, 1, 16, 1024} { + offset := offset + t.Run(fmt.Sprintf("offset=%d", offset), func(t *testing.T) { + genericCtr, multiblockCtr := makeTestingCiphers(aesBlock, iv) + + // Generate reference ciphertext. + genericCiphertext := make([]byte, Size) + genericCtr.XORKeyStream(genericCiphertext, plaintext) + + multiblockCiphertext := make([]byte, Size) + multiblockCtr.XORKeyStream(multiblockCiphertext, plaintext[:offset]) + multiblockCtr.XORKeyStream(multiblockCiphertext[offset:], plaintext[offset:]) + if !bytes.Equal(genericCiphertext, multiblockCiphertext) { + t.Fatal("multiblock CTR's output does not match generic CTR's output") + } + }) + } + }) + } + }) + } +} + +// Check that method XORKeyStreamAt works correctly. +func TestCTR_AES_multiblock_XORKeyStreamAt(t *testing.T) { + if boring.Enabled { + t.Skip("XORKeyStreamAt is not available in boring mode") + } + + r := rand.New(rand.NewSource(12345)) + const Size = 32 * 1024 * 1024 + plaintext := randBytes(t, r, Size) + + for _, keySize := range []int{16, 24, 32} { + keySize := keySize + t.Run(fmt.Sprintf("keySize=%d", keySize), func(t *testing.T) { + key := randBytes(t, r, keySize) + iv := randBytes(t, r, aesBlockSize) + + aesBlock, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + genericCtr, _ := makeTestingCiphers(aesBlock, iv) + ctrAt := fipsaes.NewCTR(aesBlock.(*fipsaes.Block), iv) + + // Generate reference ciphertext. + genericCiphertext := make([]byte, Size) + genericCtr.XORKeyStream(genericCiphertext, plaintext) + + multiblockCiphertext := make([]byte, Size) + // Split the range to random slices. + const N = 1000 + boundaries := make([]int, 0, N+2) + for i := 0; i < N; i++ { + boundaries = append(boundaries, r.Intn(Size)) + } + boundaries = append(boundaries, 0) + boundaries = append(boundaries, Size) + sort.Ints(boundaries) + + for _, i := range r.Perm(N + 1) { + begin := boundaries[i] + end := boundaries[i+1] + ctrAt.XORKeyStreamAt( + multiblockCiphertext[begin:end], + plaintext[begin:end], + uint64(begin), + ) + } + + if !bytes.Equal(genericCiphertext, multiblockCiphertext) { + t.Fatal("multiblock CTR's output does not match generic CTR's output") + } + }) + } +} diff --git a/crypto/cipher/ctr_test.go b/crypto/cipher/ctr_test.go index 839f16315ce..b40e9c3a3d8 100644 --- a/crypto/cipher/ctr_test.go +++ b/crypto/cipher/ctr_test.go @@ -7,18 +7,19 @@ package cipher_test import ( "bytes" "fmt" + "testing" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/des" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" - "testing" ) type noopBlock int func (b noopBlock) BlockSize() int { return int(b) } func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) } -func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) } +func (noopBlock) Decrypt(dst, src []byte) { panic("unreachable") } func inc(b []byte) { for i := len(b) - 1; i >= 0; i++ { @@ -59,23 +60,23 @@ func TestCTR(t *testing.T) { } func TestCTRStream(t *testing.T) { + cryptotest.TestAllImplementations(t, "aes", func(t *testing.T) { + for _, keylen := range []int{128, 192, 256} { + t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { + rng := newRandReader(t) - for _, keylen := range []int{128, 192, 256} { - - t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { - rng := newRandReader(t) - - key := make([]byte, keylen/8) - rng.Read(key) + key := make([]byte, keylen/8) + rng.Read(key) - block, err := aes.NewCipher(key) - if err != nil { - panic(err) - } + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } - cryptotest.TestStreamFromBlock(t, block, cipher.NewCTR) - }) - } + cryptotest.TestStreamFromBlock(t, block, cipher.NewCTR) + }) + } + }) t.Run("DES", func(t *testing.T) { rng := newRandReader(t) @@ -91,3 +92,10 @@ func TestCTRStream(t *testing.T) { cryptotest.TestStreamFromBlock(t, block, cipher.NewCTR) }) } + +func TestCTRExtraMethods(t *testing.T) { + block, _ := aes.NewCipher(make([]byte, 16)) + iv := make([]byte, block.BlockSize()) + s := cipher.NewCTR(block, iv) + cryptotest.NoExtraMethods(t, &s) +} diff --git a/crypto/cipher/example_test.go b/crypto/cipher/example_test.go index 5f065e37b66..80e95c0484a 100644 --- a/crypto/cipher/example_test.go +++ b/crypto/cipher/example_test.go @@ -11,10 +11,9 @@ import ( "io" "os" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/rand" ) func ExampleNewGCM_encrypt() { @@ -31,14 +30,14 @@ func ExampleNewGCM_encrypt() { panic(err.Error()) } - // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. - nonce := make([]byte, 12) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + aesgcm, err := cipher.NewGCM(block) + if err != nil { panic(err.Error()) } - aesgcm, err := cipher.NewGCM(block) - if err != nil { + // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. + nonce := make([]byte, aesgcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { panic(err.Error()) } diff --git a/crypto/cipher/export_test.go b/crypto/cipher/export_test.go deleted file mode 100644 index 5ecd67b28ba..00000000000 --- a/crypto/cipher/export_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cipher - -// Export internal functions for testing. -var NewCBCGenericEncrypter = newCBCGenericEncrypter -var NewCBCGenericDecrypter = newCBCGenericDecrypter diff --git a/crypto/cipher/fuzz_test.go b/crypto/cipher/fuzz_test.go index 66c85cbe0ae..fbafa13f0a6 100644 --- a/crypto/cipher/fuzz_test.go +++ b/crypto/cipher/fuzz_test.go @@ -45,7 +45,7 @@ func TestFuzz(t *testing.T) { c, _ := aes.NewCipher(ft.key) cbcAsm := cipher.NewCBCEncrypter(c, commonIV) - cbcGeneric := cipher.NewCBCGenericEncrypter(c, commonIV) + cbcGeneric := cipher.NewCBCEncrypter(wrap(c), commonIV) if testing.Short() { timeout = time.NewTimer(10 * time.Millisecond) @@ -76,7 +76,7 @@ func TestFuzz(t *testing.T) { } cbcAsm = cipher.NewCBCDecrypter(c, commonIV) - cbcGeneric = cipher.NewCBCGenericDecrypter(c, commonIV) + cbcGeneric = cipher.NewCBCDecrypter(wrap(c), commonIV) if testing.Short() { timeout = time.NewTimer(10 * time.Millisecond) diff --git a/crypto/cipher/gcm.go b/crypto/cipher/gcm.go index 76f164e5794..5443f47aee2 100644 --- a/crypto/cipher/gcm.go +++ b/crypto/cipher/gcm.go @@ -1,4 +1,4 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -7,75 +7,20 @@ package cipher import ( "errors" - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes/gcm" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" "github.com/runZeroInc/excrypto/internal/byteorder" ) -// AEAD is a cipher mode providing authenticated encryption with associated -// data. For a description of the methodology, see -// https://en.wikipedia.org/wiki/Authenticated_encryption. -type AEAD interface { - // NonceSize returns the size of the nonce that must be passed to Seal - // and Open. - NonceSize() int - - // Overhead returns the maximum difference between the lengths of a - // plaintext and its ciphertext. - Overhead() int - - // Seal encrypts and authenticates plaintext, authenticates the - // additional data and appends the result to dst, returning the updated - // slice. The nonce must be NonceSize() bytes long and unique for all - // time, for a given key. - // - // To reuse plaintext's storage for the encrypted output, use plaintext[:0] - // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. - Seal(dst, nonce, plaintext, additionalData []byte) []byte - - // Open decrypts and authenticates ciphertext, authenticates the - // additional data and, if successful, appends the resulting plaintext - // to dst, returning the updated slice. The nonce must be NonceSize() - // bytes long and both it and the additional data must match the - // value passed to Seal. - // - // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0] - // as dst. Otherwise, the remaining capacity of dst must not overlap ciphertext. - // - // Even if the function fails, the contents of dst, up to its capacity, - // may be overwritten. - Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) -} - -// gcmAble is an interface implemented by ciphers that have a specific optimized -// implementation of GCM, like crypto/aes. NewGCM will check for this interface -// and return the specific AEAD if found. -type gcmAble interface { - NewGCM(nonceSize, tagSize int) (AEAD, error) -} - -// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM -// standard and make binary.BigEndian suitable for marshaling these values, the -// bits are stored in big endian order. For example: -// -// the coefficient of x⁰ can be obtained by v.low >> 63. -// the coefficient of x⁶³ can be obtained by v.low & 1. -// the coefficient of x⁶⁴ can be obtained by v.high >> 63. -// the coefficient of x¹²⁷ can be obtained by v.high & 1. -type gcmFieldElement struct { - low, high uint64 -} - -// gcm represents a Galois Counter Mode with a specific key. See -// https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf -type gcm struct { - cipher Block - nonceSize int - tagSize int - // productTable contains the first sixteen powers of the key, H. - // However, they are in bit reversed order. See NewGCMWithNonceSize. - productTable [16]gcmFieldElement -} +const ( + gcmBlockSize = 16 + gcmStandardNonceSize = 12 + gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. +) // NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode // with the standard nonce length. @@ -84,7 +29,10 @@ type gcm struct { // An exception is when the underlying [Block] was created by aes.NewCipher // on systems with hardware support for AES. See the [crypto/aes] package documentation for details. func NewGCM(cipher Block) (AEAD, error) { - return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize) + if fips140only.Enabled { + return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce") + } + return newGCM(cipher, gcmStandardNonceSize, gcmTagSize) } // NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois @@ -95,7 +43,10 @@ func NewGCM(cipher Block) (AEAD, error) { // cryptosystem that uses non-standard nonce lengths. All other users should use // [NewGCM], which is faster and more resistant to misuse. func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { - return newGCMWithNonceAndTagSize(cipher, size, gcmTagSize) + if fips140only.Enabled { + return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce") + } + return newGCM(cipher, size, gcmTagSize) } // NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois @@ -107,88 +58,214 @@ func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { // cryptosystem that uses non-standard tag lengths. All other users should use // [NewGCM], which is more resistant to misuse. func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) { - return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize) + if fips140only.Enabled { + return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce") + } + return newGCM(cipher, gcmStandardNonceSize, tagSize) } -func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, error) { - if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { - return nil, errors.New("cipher: incorrect tag size given to GCM") +func newGCM(cipher Block, nonceSize, tagSize int) (AEAD, error) { + c, ok := cipher.(*aes.Block) + if !ok { + if fips140only.Enabled { + return nil, errors.New("crypto/cipher: use of GCM with non-AES ciphers is not allowed in FIPS 140-only mode") + } + return newGCMFallback(cipher, nonceSize, tagSize) } + // We don't return gcm.New directly, because it would always return a non-nil + // AEAD interface value with type *gcm.GCM even if the *gcm.GCM is nil. + g, err := gcm.New(c, nonceSize, tagSize) + if err != nil { + return nil, err + } + return g, nil +} - if nonceSize <= 0 { - return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised") +// NewGCMWithRandomNonce returns the given cipher wrapped in Galois Counter +// Mode, with randomly-generated nonces. The cipher must have been created by +// [crypto/aes.NewCipher]. +// +// It generates a random 96-bit nonce, which is prepended to the ciphertext by Seal, +// and is extracted from the ciphertext by Open. The NonceSize of the AEAD is zero, +// while the Overhead is 28 bytes (the combination of nonce size and tag size). +// +// A given key MUST NOT be used to encrypt more than 2^32 messages, to limit the +// risk of a random nonce collision to negligible levels. +func NewGCMWithRandomNonce(cipher Block) (AEAD, error) { + c, ok := cipher.(*aes.Block) + if !ok { + return nil, errors.New("cipher: NewGCMWithRandomNonce requires aes.Block") + } + g, err := gcm.New(c, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err } + return gcmWithRandomNonce{g}, nil +} - if cipher, ok := cipher.(gcmAble); ok { - return cipher.NewGCM(nonceSize, tagSize) +type gcmWithRandomNonce struct { + *gcm.GCM +} + +func (g gcmWithRandomNonce) NonceSize() int { + return 0 +} + +func (g gcmWithRandomNonce) Overhead() int { + return gcmStandardNonceSize + gcmTagSize +} + +func (g gcmWithRandomNonce) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != 0 { + panic("crypto/cipher: non-empty nonce passed to GCMWithRandomNonce") } - if cipher.BlockSize() != gcmBlockSize { - return nil, errors.New("cipher: NewGCM requires 128-bit block cipher") + ret, out := sliceForAppend(dst, gcmStandardNonceSize+len(plaintext)+gcmTagSize) + if alias.InexactOverlap(out, plaintext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") } + nonce = out[:gcmStandardNonceSize] + ciphertext := out[gcmStandardNonceSize:] - var key [gcmBlockSize]byte - cipher.Encrypt(key[:], key[:]) + // The AEAD interface allows using plaintext[:0] or ciphertext[:0] as dst. + // + // This is kind of a problem when trying to prepend or trim a nonce, because the + // actual AES-GCTR blocks end up overlapping but not exactly. + // + // In Open, we write the output *before* the input, so unless we do something + // weird like working through a chunk of block backwards, it works out. + // + // In Seal, we could work through the input backwards or intentionally load + // ahead before writing. + // + // However, the crypto/internal/fips140/aes/gcm APIs also check for exact overlap, + // so for now we just do a memmove if we detect overlap. + // + // ┌───────────────────────────┬ ─ ─ + // │PPPPPPPPPPPPPPPPPPPPPPPPPPP│ │ + // └▽─────────────────────────▲┴ ─ ─ + // ╲ Seal ╲ + // ╲ Open ╲ + // ┌───▼─────────────────────────△──┐ + // │NN|CCCCCCCCCCCCCCCCCCCCCCCCCCC|T│ + // └────────────────────────────────┘ + // + if alias.AnyOverlap(out, plaintext) { + copy(ciphertext, plaintext) + plaintext = ciphertext[:len(plaintext)] + } - g := &gcm{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize} + gcm.SealWithRandomNonce(g.GCM, nonce, ciphertext, plaintext, additionalData) + return ret +} - // We precompute 16 multiples of |key|. However, when we do lookups - // into this table we'll be using bits from a field element and - // therefore the bits will be in the reverse order. So normally one - // would expect, say, 4*key to be in index 4 of the table but due to - // this bit ordering it will actually be in index 0010 (base 2) = 2. - x := gcmFieldElement{ - byteorder.BeUint64(key[:8]), - byteorder.BeUint64(key[8:]), +func (g gcmWithRandomNonce) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != 0 { + panic("crypto/cipher: non-empty nonce passed to GCMWithRandomNonce") + } + if len(ciphertext) < gcmStandardNonceSize+gcmTagSize { + return nil, errOpen } - g.productTable[reverseBits(1)] = x - for i := 2; i < 16; i += 2 { - g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)]) - g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x) + ret, out := sliceForAppend(dst, len(ciphertext)-gcmStandardNonceSize-gcmTagSize) + if alias.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") + } + // See the discussion in Seal. Note that if there is any overlap at this + // point, it's because out = ciphertext, so out must have enough capacity + // even if we sliced the tag off. Also note how [AEAD] specifies that "the + // contents of dst, up to its capacity, may be overwritten". + if alias.AnyOverlap(out, ciphertext) { + nonce = make([]byte, gcmStandardNonceSize) + copy(nonce, ciphertext) + copy(out[:len(ciphertext)], ciphertext[gcmStandardNonceSize:]) + ciphertext = out[:len(ciphertext)-gcmStandardNonceSize] + } else { + nonce = ciphertext[:gcmStandardNonceSize] + ciphertext = ciphertext[gcmStandardNonceSize:] } - return g, nil + _, err := g.GCM.Open(out[:0], nonce, ciphertext, additionalData) + if err != nil { + return nil, err + } + return ret, nil } -const ( - gcmBlockSize = 16 - gcmTagSize = 16 - gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. - gcmStandardNonceSize = 12 -) +// gcmAble is an interface implemented by ciphers that have a specific optimized +// implementation of GCM. crypto/aes doesn't use this anymore, and we'd like to +// eventually remove it. +type gcmAble interface { + NewGCM(nonceSize, tagSize int) (AEAD, error) +} -func (g *gcm) NonceSize() int { +func newGCMFallback(cipher Block, nonceSize, tagSize int) (AEAD, error) { + if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { + return nil, errors.New("cipher: incorrect tag size given to GCM") + } + if nonceSize <= 0 { + return nil, errors.New("cipher: the nonce can't have zero length") + } + if cipher, ok := cipher.(gcmAble); ok { + return cipher.NewGCM(nonceSize, tagSize) + } + if cipher.BlockSize() != gcmBlockSize { + return nil, errors.New("cipher: NewGCM requires 128-bit block cipher") + } + return &gcmFallback{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize}, nil +} + +// gcmFallback is only used for non-AES ciphers, which regrettably we +// theoretically support. It's a copy of the generic implementation from +// crypto/internal/fips140/aes/gcm/gcm_generic.go, refer to that file for more details. +type gcmFallback struct { + cipher Block + nonceSize int + tagSize int +} + +func (g *gcmFallback) NonceSize() int { return g.nonceSize } -func (g *gcm) Overhead() int { +func (g *gcmFallback) Overhead() int { return g.tagSize } -func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { +func (g *gcmFallback) Seal(dst, nonce, plaintext, additionalData []byte) []byte { if len(nonce) != g.nonceSize { panic("crypto/cipher: incorrect nonce length given to GCM") } - if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) { + if g.nonceSize == 0 { + panic("crypto/cipher: incorrect GCM nonce size") + } + if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize { panic("crypto/cipher: message too large for GCM") } ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) if alias.InexactOverlap(out, plaintext) { - panic("crypto/cipher: invalid buffer overlap") + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") } - var counter, tagMask [gcmBlockSize]byte - g.deriveCounter(&counter, nonce) - - g.cipher.Encrypt(tagMask[:], counter[:]) - gcmInc32(&counter) + var H, counter, tagMask [gcmBlockSize]byte + g.cipher.Encrypt(H[:], H[:]) + deriveCounter(&H, &counter, nonce) + gcmCounterCryptGeneric(g.cipher, tagMask[:], tagMask[:], &counter) - g.counterCrypt(out, plaintext, &counter) + gcmCounterCryptGeneric(g.cipher, out, plaintext, &counter) var tag [gcmTagSize]byte - g.auth(tag[:], out[:len(plaintext)], data, &tagMask) + gcmAuth(tag[:], &H, &tagMask, out[:len(plaintext)], additionalData) copy(out[len(plaintext):], tag[:]) return ret @@ -196,12 +273,10 @@ func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { var errOpen = errors.New("cipher: message authentication failed") -func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { +func (g *gcmFallback) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { if len(nonce) != g.nonceSize { panic("crypto/cipher: incorrect nonce length given to GCM") } - // Sanity check to prevent the authentication from always succeeding if an implementation - // leaves tagSize uninitialized, for example. if g.tagSize < gcmMinimumTagSize { panic("crypto/cipher: incorrect GCM tag size") } @@ -209,144 +284,82 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(ciphertext) < g.tagSize { return nil, errOpen } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+uint64(g.tagSize) { + if uint64(len(ciphertext)) > uint64((1<<32)-2)*gcmBlockSize+uint64(g.tagSize) { return nil, errOpen } - tag := ciphertext[len(ciphertext)-g.tagSize:] - ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + ret, out := sliceForAppend(dst, len(ciphertext)-g.tagSize) + if alias.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") + } - var counter, tagMask [gcmBlockSize]byte - g.deriveCounter(&counter, nonce) + var H, counter, tagMask [gcmBlockSize]byte + g.cipher.Encrypt(H[:], H[:]) + deriveCounter(&H, &counter, nonce) + gcmCounterCryptGeneric(g.cipher, tagMask[:], tagMask[:], &counter) - g.cipher.Encrypt(tagMask[:], counter[:]) - gcmInc32(&counter) + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] var expectedTag [gcmTagSize]byte - g.auth(expectedTag[:], ciphertext, data, &tagMask) - - ret, out := sliceForAppend(dst, len(ciphertext)) - if alias.InexactOverlap(out, ciphertext) { - panic("crypto/cipher: invalid buffer overlap") - } - + gcmAuth(expectedTag[:], &H, &tagMask, ciphertext, additionalData) if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { - // The AESNI code decrypts and authenticates concurrently, and - // so overwrites dst in the event of a tag mismatch. That - // behavior is mimicked here in order to be consistent across - // platforms. + // We sometimes decrypt and authenticate concurrently, so we overwrite + // dst in the event of a tag mismatch. To be consistent across platforms + // and to avoid releasing unauthenticated plaintext, we clear the buffer + // in the event of an error. clear(out) return nil, errOpen } - g.counterCrypt(out, ciphertext, &counter) + gcmCounterCryptGeneric(g.cipher, out, ciphertext, &counter) return ret, nil } -// reverseBits reverses the order of the bits of 4-bit number in i. -func reverseBits(i int) int { - i = ((i << 2) & 0xc) | ((i >> 2) & 0x3) - i = ((i << 1) & 0xa) | ((i >> 1) & 0x5) - return i -} - -// gcmAdd adds two elements of GF(2¹²⁸) and returns the sum. -func gcmAdd(x, y *gcmFieldElement) gcmFieldElement { - // Addition in a characteristic 2 field is just XOR. - return gcmFieldElement{x.low ^ y.low, x.high ^ y.high} -} - -// gcmDouble returns the result of doubling an element of GF(2¹²⁸). -func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) { - msbSet := x.high&1 == 1 - - // Because of the bit-ordering, doubling is actually a right shift. - double.high = x.high >> 1 - double.high |= x.low << 63 - double.low = x.low >> 1 - - // If the most-significant bit was set before shifting then it, - // conceptually, becomes a term of x^128. This is greater than the - // irreducible polynomial so the result has to be reduced. The - // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to - // eliminate the term at x^128 which also means subtracting the other - // four terms. In characteristic 2 fields, subtraction == addition == - // XOR. - if msbSet { - double.low ^= 0xe100000000000000 +func deriveCounter(H, counter *[gcmBlockSize]byte, nonce []byte) { + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + lenBlock := make([]byte, 16) + byteorder.BEPutUint64(lenBlock[8:], uint64(len(nonce))*8) + J := gcm.GHASH(H, nonce, lenBlock) + copy(counter[:], J) } - - return } -var gcmReductionTable = []uint16{ - 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, - 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, -} - -// mul sets y to y*H, where H is the GCM key, fixed during NewGCMWithNonceSize. -func (g *gcm) mul(y *gcmFieldElement) { - var z gcmFieldElement - - for i := 0; i < 2; i++ { - word := y.high - if i == 1 { - word = y.low - } +func gcmCounterCryptGeneric(b Block, out, src []byte, counter *[gcmBlockSize]byte) { + var mask [gcmBlockSize]byte + for len(src) >= gcmBlockSize { + b.Encrypt(mask[:], counter[:]) + gcmInc32(counter) - // Multiplication works by multiplying z by 16 and adding in - // one of the precomputed multiples of H. - for j := 0; j < 64; j += 4 { - msw := z.high & 0xf - z.high >>= 4 - z.high |= z.low << 60 - z.low >>= 4 - z.low ^= uint64(gcmReductionTable[msw]) << 48 - - // the values in |table| are ordered for - // little-endian bit positions. See the comment - // in NewGCMWithNonceSize. - t := &g.productTable[word&0xf] - - z.low ^= t.low - z.high ^= t.high - word >>= 4 - } + subtle.XORBytes(out, src, mask[:]) + out = out[gcmBlockSize:] + src = src[gcmBlockSize:] } - - *y = z -} - -// updateBlocks extends y with more polynomial terms from blocks, based on -// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks. -func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) { - for len(blocks) > 0 { - y.low ^= byteorder.BeUint64(blocks) - y.high ^= byteorder.BeUint64(blocks[8:]) - g.mul(y) - blocks = blocks[gcmBlockSize:] + if len(src) > 0 { + b.Encrypt(mask[:], counter[:]) + gcmInc32(counter) + subtle.XORBytes(out, src, mask[:]) } } -// update extends y with more polynomial terms from data. If data is not a -// multiple of gcmBlockSize bytes long then the remainder is zero padded. -func (g *gcm) update(y *gcmFieldElement, data []byte) { - fullBlocks := (len(data) >> 4) << 4 - g.updateBlocks(y, data[:fullBlocks]) - - if len(data) != fullBlocks { - var partialBlock [gcmBlockSize]byte - copy(partialBlock[:], data[fullBlocks:]) - g.updateBlocks(y, partialBlock[:]) - } +func gcmInc32(counterBlock *[gcmBlockSize]byte) { + ctr := counterBlock[len(counterBlock)-4:] + byteorder.BEPutUint32(ctr, byteorder.BEUint32(ctr)+1) } -// gcmInc32 treats the final four bytes of counterBlock as a big-endian value -// and increments it. -func gcmInc32(counterBlock *[16]byte) { - ctr := counterBlock[len(counterBlock)-4:] - byteorder.BePutUint32(ctr, byteorder.BeUint32(ctr)+1) +func gcmAuth(out []byte, H, tagMask *[gcmBlockSize]byte, ciphertext, additionalData []byte) { + lenBlock := make([]byte, 16) + byteorder.BEPutUint64(lenBlock[:8], uint64(len(additionalData))*8) + byteorder.BEPutUint64(lenBlock[8:], uint64(len(ciphertext))*8) + S := gcm.GHASH(H, additionalData, ciphertext, lenBlock) + subtle.XORBytes(out, S, tagMask[:]) } // sliceForAppend takes a slice and a requested number of bytes. It returns a @@ -363,64 +376,3 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) { tail = head[len(in):] return } - -// counterCrypt crypts in to out using g.cipher in counter mode. -func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { - var mask [gcmBlockSize]byte - - for len(in) >= gcmBlockSize { - g.cipher.Encrypt(mask[:], counter[:]) - gcmInc32(counter) - - subtle.XORBytes(out, in, mask[:]) - out = out[gcmBlockSize:] - in = in[gcmBlockSize:] - } - - if len(in) > 0 { - g.cipher.Encrypt(mask[:], counter[:]) - gcmInc32(counter) - subtle.XORBytes(out, in, mask[:]) - } -} - -// deriveCounter computes the initial GCM counter state from the given nonce. -// See NIST SP 800-38D, section 7.1. This assumes that counter is filled with -// zeros on entry. -func (g *gcm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) { - // GCM has two modes of operation with respect to the initial counter - // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" - // for nonces of other lengths. For a 96-bit nonce, the nonce, along - // with a four-byte big-endian counter starting at one, is used - // directly as the starting counter. For other nonce sizes, the counter - // is computed by passing it through the GHASH function. - if len(nonce) == gcmStandardNonceSize { - copy(counter[:], nonce) - counter[gcmBlockSize-1] = 1 - } else { - var y gcmFieldElement - g.update(&y, nonce) - y.high ^= uint64(len(nonce)) * 8 - g.mul(&y) - byteorder.BePutUint64(counter[:8], y.low) - byteorder.BePutUint64(counter[8:], y.high) - } -} - -// auth calculates GHASH(ciphertext, additionalData), masks the result with -// tagMask and writes the result to out. -func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { - var y gcmFieldElement - g.update(&y, additionalData) - g.update(&y, ciphertext) - - y.low ^= uint64(len(additionalData)) * 8 - y.high ^= uint64(len(ciphertext)) * 8 - - g.mul(&y) - - byteorder.BePutUint64(out, y.low) - byteorder.BePutUint64(out[8:], y.high) - - subtle.XORBytes(out, out, tagMask[:]) -} diff --git a/crypto/cipher/gcm_test.go b/crypto/cipher/gcm_test.go index acde1a81ca9..156c3c4ac13 100644 --- a/crypto/cipher/gcm_test.go +++ b/crypto/cipher/gcm_test.go @@ -6,6 +6,7 @@ package cipher_test import ( "bytes" + "crypto/rand" "encoding/hex" "errors" "fmt" @@ -13,13 +14,51 @@ import ( "reflect" "testing" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + fipsaes "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes/gcm" ) +var _ cipher.Block = (*wrapper)(nil) + +type wrapper struct { + block cipher.Block +} + +func (w *wrapper) BlockSize() int { return w.block.BlockSize() } +func (w *wrapper) Encrypt(dst, src []byte) { w.block.Encrypt(dst, src) } +func (w *wrapper) Decrypt(dst, src []byte) { w.block.Decrypt(dst, src) } + +// wrap wraps the Block so that it does not type-asserts to *aes.Block. +func wrap(b cipher.Block) cipher.Block { + return &wrapper{b} +} + +func testAllImplementations(t *testing.T, f func(*testing.T, func([]byte) cipher.Block)) { + cryptotest.TestAllImplementations(t, "gcm", func(t *testing.T) { + f(t, func(b []byte) cipher.Block { + c, err := aes.NewCipher(b) + if err != nil { + t.Fatal(err) + } + return c + }) + }) + t.Run("Fallback", func(t *testing.T) { + f(t, func(b []byte) cipher.Block { + c, err := aes.NewCipher(b) + if err != nil { + t.Fatal(err) + } + return wrap(c) + }) + }) +} + var aesGCMTests = []struct { key, nonce, plaintext, ad, result string }{ @@ -376,18 +415,20 @@ var aesGCMTests = []struct { } func TestAESGCM(t *testing.T) { + testAllImplementations(t, testAESGCM) +} + +func testAESGCM(t *testing.T, newCipher func(key []byte) cipher.Block) { for i, test := range aesGCMTests { key, _ := hex.DecodeString(test.key) - aes, err := aes.NewCipher(key) - if err != nil { - t.Fatal(err) - } + aes := newCipher(key) nonce, _ := hex.DecodeString(test.nonce) plaintext, _ := hex.DecodeString(test.plaintext) ad, _ := hex.DecodeString(test.ad) tagSize := (len(test.result) - len(test.plaintext)) / 2 + var err error var aesgcm cipher.AEAD switch { // Handle non-standard tag sizes @@ -459,19 +500,26 @@ func TestAESGCM(t *testing.T) { } func TestGCMInvalidTagSize(t *testing.T) { - key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed") + testAllImplementations(t, testGCMInvalidTagSize) +} - aes, _ := aes.NewCipher(key) +func testGCMInvalidTagSize(t *testing.T, newCipher func(key []byte) cipher.Block) { + key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed") + aes := newCipher(key) for _, tagSize := range []int{0, 1, aes.BlockSize() + 1} { aesgcm, err := cipher.NewGCMWithTagSize(aes, tagSize) if aesgcm != nil || err == nil { - t.Fatalf("NewGCMWithNonceAndTagSize was successful with an invalid %d-byte tag size", tagSize) + t.Fatalf("NewGCMWithTagSize was successful with an invalid %d-byte tag size", tagSize) } } } func TestTagFailureOverwrite(t *testing.T) { + testAllImplementations(t, testTagFailureOverwrite) +} + +func testTagFailureOverwrite(t *testing.T, newCipher func(key []byte) cipher.Block) { // The AESNI GCM code decrypts and authenticates concurrently and so // overwrites the output buffer before checking the authentication tag. // In order to be consistent across platforms, all implementations @@ -481,7 +529,7 @@ func TestTagFailureOverwrite(t *testing.T) { nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db") ciphertext, _ := hex.DecodeString("0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c") - aes, _ := aes.NewCipher(key) + aes := newCipher(key) aesgcm, _ := cipher.NewGCM(aes) dst := make([]byte, len(ciphertext)-16) @@ -506,6 +554,10 @@ func TestTagFailureOverwrite(t *testing.T) { } func TestGCMCounterWrap(t *testing.T) { + testAllImplementations(t, testGCMCounterWrap) +} + +func testGCMCounterWrap(t *testing.T, newCipher func(key []byte) cipher.Block) { // Test that the last 32-bits of the counter wrap correctly. tests := []struct { nonce, tag string @@ -518,10 +570,7 @@ func TestGCMCounterWrap(t *testing.T) { {"010ae3d486", "5405bb490b1f95d01e2ba735687154bc"}, // counter: e36c18e69406c49722808104fffffff8 {"01b1107a9d", "939a585f342e01e17844627492d44dbf"}, // counter: e6d56eaf9127912b6d62c6dcffffffff } - key, err := aes.NewCipher(make([]byte, 16)) - if err != nil { - t.Fatal(err) - } + key := newCipher(make([]byte, 16)) plaintext := make([]byte, 16*17+1) for i, test := range tests { nonce, _ := hex.DecodeString(test.nonce) @@ -541,22 +590,6 @@ func TestGCMCounterWrap(t *testing.T) { } } -var _ cipher.Block = (*wrapper)(nil) - -type wrapper struct { - block cipher.Block -} - -func (w *wrapper) BlockSize() int { return w.block.BlockSize() } -func (w *wrapper) Encrypt(dst, src []byte) { w.block.Encrypt(dst, src) } -func (w *wrapper) Decrypt(dst, src []byte) { w.block.Decrypt(dst, src) } - -// wrap wraps the Block interface so that it does not fulfill -// any optimizing interfaces such as gcmAble. -func wrap(b cipher.Block) cipher.Block { - return &wrapper{b} -} - func TestGCMAsm(t *testing.T) { // Create a new pair of AEADs, one using the assembly implementation // and one using the generic Go implementation. @@ -661,6 +694,10 @@ func TestGCMAsm(t *testing.T) { // Test GCM against the general cipher.AEAD interface tester. func TestGCMAEAD(t *testing.T) { + testAllImplementations(t, testGCMAEAD) +} + +func testGCMAEAD(t *testing.T, newCipher func(key []byte) cipher.Block) { minTagSize := 12 for _, keySize := range []int{128, 192, 256} { @@ -671,10 +708,7 @@ func TestGCMAEAD(t *testing.T) { key := make([]byte, keySize/8) rng.Read(key) - block, err := aes.NewCipher(key) - if err != nil { - panic(err) - } + block := newCipher(key) // Test GCM with the current AES block with the standard nonce and tag // sizes. @@ -688,10 +722,184 @@ func TestGCMAEAD(t *testing.T) { // Test non-standard nonce sizes. for _, nonceSize := range []int{1, 16, 100} { t.Run(fmt.Sprintf("NonceSize-%d", nonceSize), func(t *testing.T) { - cryptotest.TestAEAD(t, func() (cipher.AEAD, error) { return cipher.NewGCMWithNonceSize(block, nonceSize) }) }) } + + // Test NewGCMWithRandomNonce. + t.Run("GCMWithRandomNonce", func(t *testing.T) { + if _, ok := block.(*wrapper); ok || boring.Enabled { + t.Skip("NewGCMWithRandomNonce requires an AES block cipher") + } + cryptotest.TestAEAD(t, func() (cipher.AEAD, error) { return cipher.NewGCMWithRandomNonce(block) }) + }) + }) + } +} + +func TestGCMExtraMethods(t *testing.T) { + testAllImplementations(t, func(t *testing.T, newCipher func([]byte) cipher.Block) { + t.Run("NewGCM", func(t *testing.T) { + a, _ := cipher.NewGCM(newCipher(make([]byte, 16))) + cryptotest.NoExtraMethods(t, &a) + }) + t.Run("NewGCMWithTagSize", func(t *testing.T) { + a, _ := cipher.NewGCMWithTagSize(newCipher(make([]byte, 16)), 12) + cryptotest.NoExtraMethods(t, &a) }) + t.Run("NewGCMWithNonceSize", func(t *testing.T) { + a, _ := cipher.NewGCMWithNonceSize(newCipher(make([]byte, 16)), 12) + cryptotest.NoExtraMethods(t, &a) + }) + t.Run("NewGCMWithRandomNonce", func(t *testing.T) { + block := newCipher(make([]byte, 16)) + if _, ok := block.(*wrapper); ok || boring.Enabled { + t.Skip("NewGCMWithRandomNonce requires an AES block cipher") + } + a, _ := cipher.NewGCMWithRandomNonce(block) + cryptotest.NoExtraMethods(t, &a) + }) + }) +} + +func TestFIPSServiceIndicator(t *testing.T) { + newGCM := func() cipher.AEAD { + key := make([]byte, 16) + block, _ := fipsaes.New(key) + aead, _ := gcm.NewGCMWithCounterNonce(block) + return aead + } + tryNonce := func(aead cipher.AEAD, nonce []byte) bool { + fips140.ResetServiceIndicator() + aead.Seal(nil, nonce, []byte("x"), nil) + return fips140.ServiceIndicator() + } + expectTrue := func(t *testing.T, aead cipher.AEAD, nonce []byte) { + t.Helper() + if !tryNonce(aead, nonce) { + t.Errorf("expected service indicator true for %x", nonce) + } + } + expectPanic := func(t *testing.T, aead cipher.AEAD, nonce []byte) { + t.Helper() + defer func() { + t.Helper() + if recover() == nil { + t.Errorf("expected panic for %x", nonce) + } + }() + tryNonce(aead, nonce) + } + + g := newGCM() + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}) + expectTrue(t, g, []byte{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}) + // Changed name. + expectPanic(t, g, []byte{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}) + + g = newGCM() + expectTrue(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) + // Went down. + expectPanic(t, g, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + + g = newGCM() + expectTrue(t, g, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}) + expectTrue(t, g, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13}) + // Did not increment. + expectPanic(t, g, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13}) + + g = newGCM() + expectTrue(t, g, []byte{1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}) + expectTrue(t, g, []byte{1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) + // Wrap is ok as long as we don't run out of values. + expectTrue(t, g, []byte{1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0}) + expectTrue(t, g, []byte{1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe}) + // Run out of counters. + expectPanic(t, g, []byte{1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff}) + + g = newGCM() + expectTrue(t, g, []byte{1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) + // Wrap with overflow. + expectPanic(t, g, []byte{1, 2, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0}) +} + +func TestGCMForSSH(t *testing.T) { + // incIV from x/crypto/ssh/cipher.go. + incIV := func(iv []byte) { + for i := 4 + 7; i >= 4; i-- { + iv[i]++ + if iv[i] != 0 { + break + } + } + } + + expectOK := func(aead cipher.AEAD, iv []byte) { + aead.Seal(nil, iv, []byte("hello, world"), nil) + } + + expectPanic := func(aead cipher.AEAD, iv []byte) { + defer func() { + if recover() == nil { + t.Errorf("expected panic") + } + }() + aead.Seal(nil, iv, []byte("hello, world"), nil) + } + + key := make([]byte, 16) + block, _ := fipsaes.New(key) + aead, err := gcm.NewGCMForSSH(block) + if err != nil { + t.Fatal(err) + } + iv := decodeHex(t, "11223344"+"0000000000000000") + expectOK(aead, iv) + incIV(iv) + expectOK(aead, iv) + iv = decodeHex(t, "11223344"+"fffffffffffffffe") + expectOK(aead, iv) + incIV(iv) + expectPanic(aead, iv) + + aead, _ = gcm.NewGCMForSSH(block) + iv = decodeHex(t, "11223344"+"fffffffffffffffe") + expectOK(aead, iv) + incIV(iv) + expectOK(aead, iv) + incIV(iv) + expectOK(aead, iv) + incIV(iv) + expectOK(aead, iv) + + aead, _ = gcm.NewGCMForSSH(block) + iv = decodeHex(t, "11223344"+"aaaaaaaaaaaaaaaa") + expectOK(aead, iv) + iv = decodeHex(t, "11223344"+"ffffffffffffffff") + expectOK(aead, iv) + incIV(iv) + expectOK(aead, iv) + iv = decodeHex(t, "11223344"+"aaaaaaaaaaaaaaa8") + expectOK(aead, iv) + incIV(iv) + expectPanic(aead, iv) + iv = decodeHex(t, "11223344"+"bbbbbbbbbbbbbbbb") + expectPanic(aead, iv) +} + +func decodeHex(t *testing.T, s string) []byte { + t.Helper() + b, err := hex.DecodeString(s) + if err != nil { + t.Fatal(err) } + return b } diff --git a/crypto/cipher/modes_test.go b/crypto/cipher/modes_test.go new file mode 100644 index 00000000000..14a37835d3b --- /dev/null +++ b/crypto/cipher/modes_test.go @@ -0,0 +1,127 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "reflect" + "testing" + + . "github.com/runZeroInc/excrypto/crypto/cipher" +) + +// Historically, crypto/aes's Block would implement some undocumented +// methods for crypto/cipher to use from NewCTR, NewCBCEncrypter, etc. +// This is no longer the case, but for now test that the mechanism is +// still working until we explicitly decide to remove it. + +type block struct { + Block +} + +func (block) BlockSize() int { + return 16 +} + +type specialCTR struct { + Stream +} + +func (block) NewCTR(iv []byte) Stream { + return specialCTR{} +} + +func TestCTRAble(t *testing.T) { + b := block{} + s := NewCTR(b, make([]byte, 16)) + if _, ok := s.(specialCTR); !ok { + t.Errorf("NewCTR did not return specialCTR") + } +} + +type specialCBC struct { + BlockMode +} + +func (block) NewCBCEncrypter(iv []byte) BlockMode { + return specialCBC{} +} + +func (block) NewCBCDecrypter(iv []byte) BlockMode { + return specialCBC{} +} + +func TestCBCAble(t *testing.T) { + b := block{} + s := NewCBCEncrypter(b, make([]byte, 16)) + if _, ok := s.(specialCBC); !ok { + t.Errorf("NewCBCEncrypter did not return specialCBC") + } + s = NewCBCDecrypter(b, make([]byte, 16)) + if _, ok := s.(specialCBC); !ok { + t.Errorf("NewCBCDecrypter did not return specialCBC") + } +} + +type specialGCM struct { + AEAD +} + +func (block) NewGCM(nonceSize, tagSize int) (AEAD, error) { + return specialGCM{}, nil +} + +func TestGCM(t *testing.T) { + b := block{} + s, err := NewGCM(b) + if err != nil { + t.Errorf("NewGCM failed: %v", err) + } + if _, ok := s.(specialGCM); !ok { + t.Errorf("NewGCM did not return specialGCM") + } +} + +// TestNoExtraMethods makes sure we don't accidentally expose methods on the +// underlying implementations of modes. +func TestNoExtraMethods(t *testing.T) { + testAllImplementations(t, testNoExtraMethods) +} + +func testNoExtraMethods(t *testing.T, newBlock func([]byte) Block) { + b := newBlock(make([]byte, 16)) + + ctr := NewCTR(b, make([]byte, 16)) + ctrExpected := []string{"XORKeyStream"} + if got := exportedMethods(ctr); !reflect.DeepEqual(got, ctrExpected) { + t.Errorf("CTR: got %v, want %v", got, ctrExpected) + } + + cbc := NewCBCEncrypter(b, make([]byte, 16)) + cbcExpected := []string{"BlockSize", "CryptBlocks", "SetIV"} + if got := exportedMethods(cbc); !reflect.DeepEqual(got, cbcExpected) { + t.Errorf("CBC: got %v, want %v", got, cbcExpected) + } + cbc = NewCBCDecrypter(b, make([]byte, 16)) + if got := exportedMethods(cbc); !reflect.DeepEqual(got, cbcExpected) { + t.Errorf("CBC: got %v, want %v", got, cbcExpected) + } + + gcm, _ := NewGCM(b) + gcmExpected := []string{"NonceSize", "Open", "Overhead", "Seal"} + if got := exportedMethods(gcm); !reflect.DeepEqual(got, gcmExpected) { + t.Errorf("GCM: got %v, want %v", got, gcmExpected) + } +} + +func exportedMethods(x any) []string { + var methods []string + v := reflect.ValueOf(x) + for i := 0; i < v.NumMethod(); i++ { + if v.Type().Method(i).IsExported() { + methods = append(methods, v.Type().Method(i).Name) + } + } + return methods +} diff --git a/crypto/cipher/ofb.go b/crypto/cipher/ofb.go index 962e38f57ea..b0db48f28d6 100644 --- a/crypto/cipher/ofb.go +++ b/crypto/cipher/ofb.go @@ -7,7 +7,8 @@ package cipher import ( - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -21,7 +22,17 @@ type ofb struct { // NewOFB returns a [Stream] that encrypts or decrypts using the block cipher b // in output feedback mode. The initialization vector iv's length must be equal // to b's block size. +// +// Deprecated: OFB mode is not authenticated, which generally enables active +// attacks to manipulate and recover the plaintext. It is recommended that +// applications use [AEAD] modes instead. The standard library implementation of +// OFB is also unoptimized and not validated as part of the FIPS 140-3 module. +// If an unauthenticated [Stream] mode is required, use [NewCTR] instead. func NewOFB(b Block, iv []byte) Stream { + if fips140only.Enabled { + panic("crypto/cipher: use of OFB is not allowed in FIPS 140-only mode") + } + blockSize := b.BlockSize() if len(iv) != blockSize { panic("cipher.NewOFB: IV length must equal block size") diff --git a/crypto/cipher/ofb_test.go b/crypto/cipher/ofb_test.go index c575547c1b0..5e449f1b96b 100644 --- a/crypto/cipher/ofb_test.go +++ b/crypto/cipher/ofb_test.go @@ -13,11 +13,12 @@ package cipher_test import ( "bytes" "fmt" + "testing" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/des" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" - "testing" ) type ofbTest struct { diff --git a/crypto/crypto.go b/crypto/crypto.go index 2774a6b6815..f2c66294811 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -6,9 +6,10 @@ package crypto import ( - "hash" "io" "strconv" + + "github.com/runZeroInc/excrypto/hash" ) // Hash identifies a cryptographic hash function that is implemented in another @@ -198,6 +199,23 @@ type Signer interface { Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error) } +// MessageSigner is an interface for an opaque private key that can be used for +// signing operations where the message is not pre-hashed by the caller. +// It is a superset of the Signer interface so that it can be passed to APIs +// which accept Signer, which may try to do an interface upgrade. +// +// MessageSigner.SignMessage and MessageSigner.Sign should produce the same +// result given the same opts. In particular, MessageSigner.SignMessage should +// only accept a zero opts.HashFunc if the Signer would also accept messages +// which are not pre-hashed. +// +// Implementations which do not provide the pre-hashed Sign API should implement +// Signer.Sign by always returning an error. +type MessageSigner interface { + Signer + SignMessage(rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error) +} + // SignerOpts contains options for signing with a [Signer]. type SignerOpts interface { // HashFunc returns an identifier for the hash function used to produce @@ -221,3 +239,18 @@ type Decrypter interface { } type DecrypterOpts any + +// SignMessage signs msg with signer. If signer implements [MessageSigner], +// [MessageSigner.SignMessage] is called directly. Otherwise, msg is hashed +// with opts.HashFunc() and signed with [Signer.Sign]. +func SignMessage(signer Signer, rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error) { + if ms, ok := signer.(MessageSigner); ok { + return ms.SignMessage(rand, msg, opts) + } + if opts.HashFunc() != 0 { + h := opts.HashFunc().New() + h.Write(msg) + msg = h.Sum(nil) + } + return signer.Sign(rand, msg, opts) +} diff --git a/crypto/des/block.go b/crypto/des/block.go index 7267a04294d..0ab6f5323c3 100644 --- a/crypto/des/block.go +++ b/crypto/des/block.go @@ -5,12 +5,13 @@ package des import ( - "github.com/runZeroInc/excrypto/internal/byteorder" "sync" + + "github.com/runZeroInc/excrypto/internal/byteorder" ) func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) { - b := byteorder.BeUint64(src) + b := byteorder.BEUint64(src) b = permuteInitialBlock(b) left, right := uint32(b>>32), uint32(b) @@ -32,7 +33,7 @@ func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) { // switch left & right and perform final permutation preOutput := (uint64(right) << 32) | uint64(left) - byteorder.BePutUint64(dst, permuteFinalBlock(preOutput)) + byteorder.BEPutUint64(dst, permuteFinalBlock(preOutput)) } // DES Feistel function. feistelBox must be initialized via @@ -218,7 +219,7 @@ func (c *desCipher) generateSubkeys(keyBytes []byte) { feistelBoxOnce.Do(initFeistelBox) // apply PC1 permutation to key - key := byteorder.BeUint64(keyBytes) + key := byteorder.BEUint64(keyBytes) permutedKey := permuteBlock(key, permutedChoice1[:]) // rotate halves of permuted key according to the rotation schedule diff --git a/crypto/des/cipher.go b/crypto/des/cipher.go index 2cdacd9c73d..d0d111a1edd 100644 --- a/crypto/des/cipher.go +++ b/crypto/des/cipher.go @@ -5,10 +5,12 @@ package des import ( + "errors" "strconv" "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/internal/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/internal/byteorder" ) @@ -28,6 +30,10 @@ type desCipher struct { // NewCipher creates and returns a new [cipher.Block]. func NewCipher(key []byte) (cipher.Block, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/des: use of DES is not allowed in FIPS 140-only mode") + } + if len(key) != 8 { return nil, KeySizeError(len(key)) } @@ -72,6 +78,10 @@ type tripleDESCipher struct { // NewTripleDESCipher creates and returns a new [cipher.Block]. func NewTripleDESCipher(key []byte) (cipher.Block, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/des: use of TripleDES is not allowed in FIPS 140-only mode") + } + if len(key) != 24 { return nil, KeySizeError(len(key)) } @@ -96,7 +106,7 @@ func (c *tripleDESCipher) Encrypt(dst, src []byte) { panic("crypto/des: invalid buffer overlap") } - b := byteorder.BeUint64(src) + b := byteorder.BEUint64(src) b = permuteInitialBlock(b) left, right := uint32(b>>32), uint32(b) @@ -117,7 +127,7 @@ func (c *tripleDESCipher) Encrypt(dst, src []byte) { right = (right << 31) | (right >> 1) preOutput := (uint64(right) << 32) | uint64(left) - byteorder.BePutUint64(dst, permuteFinalBlock(preOutput)) + byteorder.BEPutUint64(dst, permuteFinalBlock(preOutput)) } func (c *tripleDESCipher) Decrypt(dst, src []byte) { @@ -131,7 +141,7 @@ func (c *tripleDESCipher) Decrypt(dst, src []byte) { panic("crypto/des: invalid buffer overlap") } - b := byteorder.BeUint64(src) + b := byteorder.BEUint64(src) b = permuteInitialBlock(b) left, right := uint32(b>>32), uint32(b) @@ -152,5 +162,5 @@ func (c *tripleDESCipher) Decrypt(dst, src []byte) { right = (right << 31) | (right >> 1) preOutput := (uint64(right) << 32) | uint64(left) - byteorder.BePutUint64(dst, permuteFinalBlock(preOutput)) + byteorder.BEPutUint64(dst, permuteFinalBlock(preOutput)) } diff --git a/crypto/des/des_test.go b/crypto/des/des_test.go index 8aad27063f2..9c46a91232d 100644 --- a/crypto/des/des_test.go +++ b/crypto/des/des_test.go @@ -6,10 +6,11 @@ package des_test import ( "bytes" + "testing" + "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/des" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" - "testing" ) type CryptTest struct { diff --git a/crypto/dsa/dsa.go b/crypto/dsa/dsa.go index 489547d0bd5..1602f66f5e7 100644 --- a/crypto/dsa/dsa.go +++ b/crypto/dsa/dsa.go @@ -18,6 +18,7 @@ import ( "io" "math/big" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/internal/randutil" ) @@ -63,6 +64,10 @@ const numMRTests = 64 // GenerateParameters puts a random, valid set of DSA parameters into params. // This function can take many seconds, even on fast machines. func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error { + if fips140only.Enabled { + return errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode") + } + // This function doesn't follow FIPS 186-3 exactly in that it doesn't // use a verification seed to generate the primes. The verification // seed doesn't appear to be exported or used by other code and @@ -157,6 +162,10 @@ GeneratePrimes: // GenerateKey generates a public&private key pair. The Parameters of the // [PrivateKey] must already be valid (see [GenerateParameters]). func GenerateKey(priv *PrivateKey, rand io.Reader) error { + if fips140only.Enabled { + return errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode") + } + if priv.P == nil || priv.Q == nil || priv.G == nil { return errors.New("crypto/dsa: parameters not set up before generating key") } @@ -203,6 +212,10 @@ func fermatInverse(k, P *big.Int) *big.Int { // Be aware that calling Sign with an attacker-controlled [PrivateKey] may // require an arbitrary amount of CPU. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + if fips140only.Enabled { + return nil, nil, errors.New("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode") + } + randutil.MaybeReadByte(rand) // FIPS 186-3, section 4.6 @@ -271,6 +284,10 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err // to the byte-length of the subgroup. This function does not perform that // truncation itself. func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + if fips140only.Enabled { + panic("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode") + } + // FIPS 186-3, section 4.7 if pub.P.Sign() == 0 { diff --git a/crypto/dsa/dsa/dsa.go b/crypto/dsa/dsa/dsa.go deleted file mode 100644 index b68c84e896f..00000000000 --- a/crypto/dsa/dsa/dsa.go +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3. -// -// The DSA operations in this package are not implemented using constant-time algorithms. -// -// Warning: DSA is a legacy algorithm, and modern alternatives such as -// Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys -// with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while -// bigger keys are not widely supported. Note that FIPS 186-5 no longer approves -// DSA for signature generation. -package dsa - -import ( - "errors" - "io" - "math/big" - - "github.com/runZeroInc/excrypto/crypto/internal/randutil" -) - -// Parameters represents the domain parameters for a key. These parameters can -// be shared across many keys. The bit length of Q must be a multiple of 8. -type Parameters struct { - P, Q, G *big.Int -} - -// PublicKey represents a DSA public key. -type PublicKey struct { - Parameters - Y *big.Int -} - -// PrivateKey represents a DSA private key. -type PrivateKey struct { - PublicKey - X *big.Int -} - -// ErrInvalidPublicKey results when a public key is not usable by this code. -// FIPS is quite strict about the format of DSA keys, but other code may be -// less so. Thus, when using keys which may have been generated by other code, -// this error must be handled. -var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key") - -// ParameterSizes is an enumeration of the acceptable bit lengths of the primes -// in a set of DSA parameters. See FIPS 186-3, section 4.2. -type ParameterSizes int - -const ( - L1024N160 ParameterSizes = iota - L2048N224 - L2048N256 - L3072N256 -) - -// numMRTests is the number of Miller-Rabin primality tests that we perform. We -// pick the largest recommended number from table C.1 of FIPS 186-3. -const numMRTests = 64 - -// GenerateParameters puts a random, valid set of DSA parameters into params. -// This function can take many seconds, even on fast machines. -func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error { - // This function doesn't follow FIPS 186-3 exactly in that it doesn't - // use a verification seed to generate the primes. The verification - // seed doesn't appear to be exported or used by other code and - // omitting it makes the code cleaner. - - var L, N int - switch sizes { - case L1024N160: - L = 1024 - N = 160 - case L2048N224: - L = 2048 - N = 224 - case L2048N256: - L = 2048 - N = 256 - case L3072N256: - L = 3072 - N = 256 - default: - return errors.New("crypto/dsa: invalid ParameterSizes") - } - - qBytes := make([]byte, N/8) - pBytes := make([]byte, L/8) - - q := new(big.Int) - p := new(big.Int) - rem := new(big.Int) - one := new(big.Int) - one.SetInt64(1) - -GeneratePrimes: - for { - if _, err := io.ReadFull(rand, qBytes); err != nil { - return err - } - - qBytes[len(qBytes)-1] |= 1 - qBytes[0] |= 0x80 - q.SetBytes(qBytes) - - if !q.ProbablyPrime(numMRTests) { - continue - } - - for i := 0; i < 4*L; i++ { - if _, err := io.ReadFull(rand, pBytes); err != nil { - return err - } - - pBytes[len(pBytes)-1] |= 1 - pBytes[0] |= 0x80 - - p.SetBytes(pBytes) - rem.Mod(p, q) - rem.Sub(rem, one) - p.Sub(p, rem) - if p.BitLen() < L { - continue - } - - if !p.ProbablyPrime(numMRTests) { - continue - } - - params.P = p - params.Q = q - break GeneratePrimes - } - } - - h := new(big.Int) - h.SetInt64(2) - g := new(big.Int) - - pm1 := new(big.Int).Sub(p, one) - e := new(big.Int).Div(pm1, q) - - for { - g.Exp(h, e, p) - if g.Cmp(one) == 0 { - h.Add(h, one) - continue - } - - params.G = g - return nil - } -} - -// GenerateKey generates a public&private key pair. The Parameters of the -// PrivateKey must already be valid (see GenerateParameters). -func GenerateKey(priv *PrivateKey, rand io.Reader) error { - if priv.P == nil || priv.Q == nil || priv.G == nil { - return errors.New("crypto/dsa: parameters not set up before generating key") - } - - x := new(big.Int) - xBytes := make([]byte, priv.Q.BitLen()/8) - - for { - _, err := io.ReadFull(rand, xBytes) - if err != nil { - return err - } - x.SetBytes(xBytes) - if x.Sign() != 0 && x.Cmp(priv.Q) < 0 { - break - } - } - - priv.X = x - priv.Y = new(big.Int) - priv.Y.Exp(priv.G, x, priv.P) - return nil -} - -// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. -// This has better constant-time properties than Euclid's method (implemented -// in math/big.Int.ModInverse) although math/big itself isn't strictly -// constant-time so it's not perfect. -func fermatInverse(k, P *big.Int) *big.Int { - two := big.NewInt(2) - pMinus2 := new(big.Int).Sub(P, two) - return new(big.Int).Exp(k, pMinus2, P) -} - -// Sign signs an arbitrary length hash (which should be the result of hashing a -// larger message) using the private key, priv. It returns the signature as a -// pair of integers. The security of the private key depends on the entropy of -// rand. -// -// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated -// to the byte-length of the subgroup. This function does not perform that -// truncation itself. -// -// Be aware that calling Sign with an attacker-controlled PrivateKey may -// require an arbitrary amount of CPU. -func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { - randutil.MaybeReadByte(rand) - - // FIPS 186-3, section 4.6 - - n := priv.Q.BitLen() - if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n%8 != 0 { - err = ErrInvalidPublicKey - return - } - n >>= 3 - - var attempts int - for attempts = 10; attempts > 0; attempts-- { - k := new(big.Int) - buf := make([]byte, n) - for { - _, err = io.ReadFull(rand, buf) - if err != nil { - return - } - k.SetBytes(buf) - // priv.Q must be >= 128 because the test above - // requires it to be > 0 and that - // ceil(log_2(Q)) mod 8 = 0 - // Thus this loop will quickly terminate. - if k.Sign() > 0 && k.Cmp(priv.Q) < 0 { - break - } - } - - kInv := fermatInverse(k, priv.Q) - - r = new(big.Int).Exp(priv.G, k, priv.P) - r.Mod(r, priv.Q) - - if r.Sign() == 0 { - continue - } - - z := k.SetBytes(hash) - - s = new(big.Int).Mul(priv.X, r) - s.Add(s, z) - s.Mod(s, priv.Q) - s.Mul(s, kInv) - s.Mod(s, priv.Q) - - if s.Sign() != 0 { - break - } - } - - // Only degenerate private keys will require more than a handful of - // attempts. - if attempts == 0 { - return nil, nil, ErrInvalidPublicKey - } - - return -} - -// Verify verifies the signature in r, s of hash using the public key, pub. It -// reports whether the signature is valid. -// -// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated -// to the byte-length of the subgroup. This function does not perform that -// truncation itself. -func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - // FIPS 186-3, section 4.7 - - if pub.P.Sign() == 0 { - return false - } - - if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 { - return false - } - if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 { - return false - } - - w := new(big.Int).ModInverse(s, pub.Q) - if w == nil { - return false - } - - n := pub.Q.BitLen() - if n%8 != 0 { - return false - } - z := new(big.Int).SetBytes(hash) - - u1 := new(big.Int).Mul(z, w) - u1.Mod(u1, pub.Q) - u2 := w.Mul(r, w) - u2.Mod(u2, pub.Q) - v := u1.Exp(pub.G, u1, pub.P) - u2.Exp(pub.Y, u2, pub.P) - v.Mul(v, u2) - v.Mod(v, pub.P) - v.Mod(v, pub.Q) - - return v.Cmp(r) == 0 -} diff --git a/crypto/dsa/dsa/dsa_test.go b/crypto/dsa/dsa/dsa_test.go deleted file mode 100644 index e869d149cf6..00000000000 --- a/crypto/dsa/dsa/dsa_test.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dsa - -import ( - "math/big" - "testing" - - "crypto/rand" -) - -func testSignAndVerify(t *testing.T, i int, priv *PrivateKey) { - hashed := []byte("testing") - r, s, err := Sign(rand.Reader, priv, hashed) - if err != nil { - t.Errorf("%d: error signing: %s", i, err) - return - } - - if !Verify(&priv.PublicKey, hashed, r, s) { - t.Errorf("%d: Verify failed", i) - } -} - -func testParameterGeneration(t *testing.T, sizes ParameterSizes, L, N int) { - var priv PrivateKey - params := &priv.Parameters - - err := GenerateParameters(params, rand.Reader, sizes) - if err != nil { - t.Errorf("%d: %s", int(sizes), err) - return - } - - if params.P.BitLen() != L { - t.Errorf("%d: params.BitLen got:%d want:%d", int(sizes), params.P.BitLen(), L) - } - - if params.Q.BitLen() != N { - t.Errorf("%d: q.BitLen got:%d want:%d", int(sizes), params.Q.BitLen(), L) - } - - one := new(big.Int) - one.SetInt64(1) - pm1 := new(big.Int).Sub(params.P, one) - quo, rem := new(big.Int).DivMod(pm1, params.Q, new(big.Int)) - if rem.Sign() != 0 { - t.Errorf("%d: p-1 mod q != 0", int(sizes)) - } - x := new(big.Int).Exp(params.G, quo, params.P) - if x.Cmp(one) == 0 { - t.Errorf("%d: invalid generator", int(sizes)) - } - - err = GenerateKey(&priv, rand.Reader) - if err != nil { - t.Errorf("error generating key: %s", err) - return - } - - testSignAndVerify(t, int(sizes), &priv) -} - -func TestParameterGeneration(t *testing.T) { - if testing.Short() { - t.Skip("skipping parameter generation test in short mode") - } - - testParameterGeneration(t, L1024N160, 1024, 160) - testParameterGeneration(t, L2048N224, 2048, 224) - testParameterGeneration(t, L2048N256, 2048, 256) - testParameterGeneration(t, L3072N256, 3072, 256) -} - -func fromHex(s string) *big.Int { - result, ok := new(big.Int).SetString(s, 16) - if !ok { - panic(s) - } - return result -} - -func TestSignAndVerify(t *testing.T) { - priv := PrivateKey{ - PublicKey: PublicKey{ - Parameters: Parameters{ - P: fromHex("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"), - Q: fromHex("E1D3391245933D68A0714ED34BBCB7A1F422B9C1"), - G: fromHex("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"), - }, - Y: fromHex("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"), - }, - X: fromHex("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A"), - } - - testSignAndVerify(t, 0, &priv) -} - -func TestSignAndVerifyWithBadPublicKey(t *testing.T) { - pub := PublicKey{ - Parameters: Parameters{ - P: fromHex("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"), - Q: fromHex("FA"), - G: fromHex("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"), - }, - Y: fromHex("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"), - } - - if Verify(&pub, []byte("testing"), fromHex("2"), fromHex("4")) { - t.Errorf("Verify unexpected success with non-existent mod inverse of Q") - } -} - -func TestSigningWithDegenerateKeys(t *testing.T) { - // Signing with degenerate private keys should not cause an infinite - // loop. - badKeys := []struct { - p, q, g, y, x string - }{ - {"00", "01", "00", "00", "00"}, - {"01", "ff", "00", "00", "00"}, - } - - for i, test := range badKeys { - priv := PrivateKey{ - PublicKey: PublicKey{ - Parameters: Parameters{ - P: fromHex(test.p), - Q: fromHex(test.q), - G: fromHex(test.g), - }, - Y: fromHex(test.y), - }, - X: fromHex(test.x), - } - - hashed := []byte("testing") - if _, _, err := Sign(rand.Reader, &priv, hashed); err == nil { - t.Errorf("#%d: unexpected success", i) - } - } -} diff --git a/crypto/dsa/dsa_test.go b/crypto/dsa/dsa_test.go index 69070473d25..ad85eac0a7f 100644 --- a/crypto/dsa/dsa_test.go +++ b/crypto/dsa/dsa_test.go @@ -5,10 +5,9 @@ package dsa import ( + "crypto/rand" "math/big" "testing" - - "crypto/rand" ) func testSignAndVerify(t *testing.T, i int, priv *PrivateKey) { diff --git a/crypto/ecdh/ecdh.go b/crypto/ecdh/ecdh.go index f7d93f52771..3e701f0e558 100644 --- a/crypto/ecdh/ecdh.go +++ b/crypto/ecdh/ecdh.go @@ -9,10 +9,10 @@ package ecdh import ( "errors" "io" - "sync" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/ecdh" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -51,14 +51,6 @@ type Curve interface { // The private method also allow us to expand the ECDH interface with more // methods in the future without breaking backwards compatibility. ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) - - // privateKeyToPublicKey converts a PrivateKey to a PublicKey. It's exposed - // as the PrivateKey.PublicKey method. - // - // This method always succeeds: for X25519, the zero key can't be - // constructed due to clamping; for NIST curves, it is rejected by - // NewPrivateKey. - privateKeyToPublicKey(*PrivateKey) *PublicKey } // PublicKey is an ECDH public key, usually a peer's ECDH share sent over the wire. @@ -70,6 +62,7 @@ type PublicKey struct { curve Curve publicKey []byte boring *boring.PublicKeyECDH + fips *ecdh.PublicKey } // Bytes returns a copy of the encoding of the public key. @@ -108,11 +101,9 @@ func (k *PublicKey) Curve() Curve { type PrivateKey struct { curve Curve privateKey []byte + publicKey *PublicKey boring *boring.PrivateKeyECDH - // publicKey is set under publicKeyOnce, to allow loading private keys with - // NewPrivateKey without having to perform a scalar multiplication. - publicKey *PublicKey - publicKeyOnce sync.Once + fips *ecdh.PrivateKey } // ECDH performs an ECDH exchange and returns the shared secret. The [PrivateKey] @@ -121,6 +112,8 @@ type PrivateKey struct { // For NIST curves, this performs ECDH as specified in SEC 1, Version 2.0, // Section 3.3.1, and returns the x-coordinate encoded according to SEC 1, // Version 2.0, Section 2.3.5. The result is never the point at infinity. +// This is also known as the Shared Secret Computation of the Ephemeral Unified +// Model scheme specified in NIST SP 800-56A Rev. 3, Section 6.1.2.2. // // For [X25519], this performs ECDH as specified in RFC 7748, Section 6.1. If // the result is the all-zero value, ECDH returns an error. @@ -151,7 +144,6 @@ func (k *PrivateKey) Equal(x crypto.PrivateKey) bool { if !ok { return false } - k.Curve() return k.curve == xx.curve && subtle.ConstantTimeCompare(k.privateKey, xx.privateKey) == 1 } @@ -161,25 +153,6 @@ func (k *PrivateKey) Curve() Curve { } func (k *PrivateKey) PublicKey() *PublicKey { - k.publicKeyOnce.Do(func() { - if k.boring != nil { - // Because we already checked in NewPrivateKey that the key is valid, - // there should not be any possible errors from BoringCrypto, - // so we turn the error into a panic. - // (We can't return it anyhow.) - kpub, err := k.boring.PublicKey() - if err != nil { - panic("boringcrypto: " + err.Error()) - } - k.publicKey = &PublicKey{ - curve: k.curve, - publicKey: kpub.Bytes(), - boring: kpub, - } - } else { - k.publicKey = k.curve.privateKeyToPublicKey(k) - } - }) return k.publicKey } diff --git a/crypto/ecdh/ecdh_test.go b/crypto/ecdh/ecdh_test.go index 826704a1eab..de82b8adf8c 100644 --- a/crypto/ecdh/ecdh_test.go +++ b/crypto/ecdh/ecdh_test.go @@ -12,13 +12,11 @@ import ( "strings" "testing" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/ecdh" + "github.com/runZeroInc/excrypto/crypto/rand" "github.com/runZeroInc/excrypto/crypto/sha256" - "github.com/runZeroInc/excrypto/x/crypto/chacha20" ) @@ -305,6 +303,8 @@ var invalidPublicKeys = map[ecdh.Curve][]string{ // Points not on the curve. "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f6", "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Non-canonical encoding. + "04ffffffff00000001000000000000000000000001000000000000000000000004ba6dbc4555a7e7fa016ec431667e8521ee35afc49b265c3accbea3f7cdb70433", }, ecdh.P384(): { // Bad lengths. @@ -319,6 +319,8 @@ var invalidPublicKeys = map[ecdh.Curve][]string{ // Points not on the curve. "04aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e60", "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Non-canonical encoding. + "04fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000100000001732152442fb6ee5c3e6ce1d920c059bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3", }, ecdh.P521(): { // Bad lengths. @@ -333,6 +335,8 @@ var invalidPublicKeys = map[ecdh.Curve][]string{ // Points not on the curve. "0400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16651", "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Non-canonical encoding. + "0402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100d9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf", }, ecdh.X25519(): {}, } @@ -420,7 +424,8 @@ package main import "github.com/runZeroInc/excrypto/crypto/ecdh" import "crypto/rand" func main() { - curve := ecdh.P384() + // Use P-256, since that's what the always-enabled CAST uses. + curve := ecdh.P256() key, err := curve.GenerateKey(rand.Reader) if err != nil { panic(err) } _, err = curve.NewPublicKey(key.PublicKey().Bytes()) @@ -433,6 +438,58 @@ func main() { } ` +/* +// TestLinker ensures that using one curve does not bring all other +// implementations into the binary. This also guarantees that govulncheck can +// avoid warning about a curve-specific vulnerability if that curve is not used. +func TestLinker(t *testing.T) { + if testing.Short() { + t.Skip("test requires running 'go build'") + } + testenv.MustHaveGoBuild(t) + + dir := t.TempDir() + hello := filepath.Join(dir, "hello.go") + err := os.WriteFile(hello, []byte(linkerTestProgram), 0664) + if err != nil { + t.Fatal(err) + } + + run := func(args ...string) string { + cmd := exec.Command(args[0], args[1:]...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%v: %v\n%s", args, err, string(out)) + } + return string(out) + } + + goBin := testenv.GoToolPath(t) + run(goBin, "build", "-o", "hello.exe", "hello.go") + if out := run("./hello.exe"); out != "OK\n" { + t.Error("unexpected output:", out) + } + + // List all text symbols under crypto/... and make sure there are some for + // P256, but none for the other curves. + var consistent bool + nm := run(goBin, "tool", "nm", "hello.exe") + for _, match := range regexp.MustCompile(`(?m)T (crypto/.*)$`).FindAllStringSubmatch(nm, -1) { + symbol := strings.ToLower(match[1]) + if strings.Contains(symbol, "p256") { + consistent = true + } + if strings.Contains(symbol, "p224") || strings.Contains(symbol, "p384") || strings.Contains(symbol, "p521") { + t.Errorf("unexpected symbol in program using only ecdh.P256: %s", match[1]) + } + } + if !consistent { + t.Error("no P256 symbols found in program using ecdh.P256, test is broken") + } +} +*/ + func TestMismatchedCurves(t *testing.T) { curves := []struct { name string diff --git a/crypto/ecdh/nist.go b/crypto/ecdh/nist.go index 3d1aaad4d99..341d630fb19 100644 --- a/crypto/ecdh/nist.go +++ b/crypto/ecdh/nist.go @@ -5,191 +5,143 @@ package ecdh import ( + "bytes" "errors" "io" - "math/bits" "github.com/runZeroInc/excrypto/crypto/internal/boring" - "github.com/runZeroInc/excrypto/crypto/internal/nistec" - "github.com/runZeroInc/excrypto/crypto/internal/randutil" - "github.com/runZeroInc/excrypto/internal/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/ecdh" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" ) -type nistCurve[Point nistPoint[Point]] struct { - name string - newPoint func() Point - scalarOrder []byte +type nistCurve struct { + name string + generate func(io.Reader) (*ecdh.PrivateKey, error) + newPrivateKey func([]byte) (*ecdh.PrivateKey, error) + newPublicKey func(publicKey []byte) (*ecdh.PublicKey, error) + sharedSecret func(*ecdh.PrivateKey, *ecdh.PublicKey) (sharedSecret []byte, err error) } -// nistPoint is a generic constraint for the nistec Point types. -type nistPoint[T any] interface { - Bytes() []byte - BytesX() ([]byte, error) - SetBytes([]byte) (T, error) - ScalarMult(T, []byte) (T, error) - ScalarBaseMult([]byte) (T, error) -} - -func (c *nistCurve[Point]) String() string { +func (c *nistCurve) String() string { return c.name } -var errInvalidPrivateKey = errors.New("crypto/ecdh: invalid private key") - -func (c *nistCurve[Point]) GenerateKey(rand io.Reader) (*PrivateKey, error) { +func (c *nistCurve) GenerateKey(rand io.Reader) (*PrivateKey, error) { if boring.Enabled && rand == boring.RandReader { key, bytes, err := boring.GenerateKeyECDH(c.name) if err != nil { return nil, err } - return newBoringPrivateKey(c, key, bytes) - } - - key := make([]byte, len(c.scalarOrder)) - randutil.MaybeReadByte(rand) - for { - if _, err := io.ReadFull(rand, key); err != nil { + pub, err := key.PublicKey() + if err != nil { return nil, err } - - // Mask off any excess bits if the size of the underlying field is not a - // whole number of bytes, which is only the case for P-521. We use a - // pointer to the scalarOrder field because comparing generic and - // instantiated types is not supported. - if &c.scalarOrder[0] == &p521Order[0] { - key[0] &= 0b0000_0001 + k := &PrivateKey{ + curve: c, + privateKey: bytes, + publicKey: &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub}, + boring: key, } + return k, nil + } - // In tests, rand will return all zeros and NewPrivateKey will reject - // the zero key as it generates the identity as a public key. This also - // makes this function consistent with crypto/elliptic.GenerateKey. - key[1] ^= 0x42 - - k, err := c.NewPrivateKey(key) - if err == errInvalidPrivateKey { - continue - } - return k, err + if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { + return nil, errors.New("crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-only mode") } -} -func (c *nistCurve[Point]) NewPrivateKey(key []byte) (*PrivateKey, error) { - if len(key) != len(c.scalarOrder) { - return nil, errors.New("crypto/ecdh: invalid private key size") + privateKey, err := c.generate(rand) + if err != nil { + return nil, err } - if isZero(key) || !isLess(key, c.scalarOrder) { - return nil, errInvalidPrivateKey + + k := &PrivateKey{ + curve: c, + privateKey: privateKey.Bytes(), + fips: privateKey, + publicKey: &PublicKey{ + curve: c, + publicKey: privateKey.PublicKey().Bytes(), + fips: privateKey.PublicKey(), + }, } if boring.Enabled { - bk, err := boring.NewPrivateKeyECDH(c.name, key) + bk, err := boring.NewPrivateKeyECDH(c.name, k.privateKey) if err != nil { return nil, err } - return newBoringPrivateKey(c, bk, key) - } - k := &PrivateKey{ - curve: c, - privateKey: append([]byte{}, key...), + pub, err := bk.PublicKey() + if err != nil { + return nil, err + } + k.boring = bk + k.publicKey.boring = pub } return k, nil } -func newBoringPrivateKey(c Curve, bk *boring.PrivateKeyECDH, privateKey []byte) (*PrivateKey, error) { - k := &PrivateKey{ - curve: c, - boring: bk, - privateKey: append([]byte(nil), privateKey...), +func (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error) { + if boring.Enabled { + bk, err := boring.NewPrivateKeyECDH(c.name, key) + if err != nil { + return nil, errors.New("crypto/ecdh: invalid private key") + } + pub, err := bk.PublicKey() + if err != nil { + return nil, errors.New("crypto/ecdh: invalid private key") + } + k := &PrivateKey{ + curve: c, + privateKey: bytes.Clone(key), + publicKey: &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub}, + boring: bk, + } + return k, nil } - return k, nil -} -func (c *nistCurve[Point]) privateKeyToPublicKey(key *PrivateKey) *PublicKey { - boring.Unreachable() - if key.curve != c { - panic("crypto/ecdh: internal error: converting the wrong key type") - } - p, err := c.newPoint().ScalarBaseMult(key.privateKey) + fk, err := c.newPrivateKey(key) if err != nil { - // This is unreachable because the only error condition of - // ScalarBaseMult is if the input is not the right size. - panic("crypto/ecdh: internal error: nistec ScalarBaseMult failed for a fixed-size input") - } - publicKey := p.Bytes() - if len(publicKey) == 1 { - // The encoding of the identity is a single 0x00 byte. This is - // unreachable because the only scalar that generates the identity is - // zero, which is rejected by NewPrivateKey. - panic("crypto/ecdh: internal error: nistec ScalarBaseMult returned the identity") - } - return &PublicKey{ - curve: key.curve, - publicKey: publicKey, - } -} - -// isZero returns whether a is all zeroes in constant time. -func isZero(a []byte) bool { - var acc byte - for _, b := range a { - acc |= b - } - return acc == 0 -} - -// isLess returns whether a < b, where a and b are big-endian buffers of the -// same length and shorter than 72 bytes. -func isLess(a, b []byte) bool { - if len(a) != len(b) { - panic("crypto/ecdh: internal error: mismatched isLess inputs") - } - - // Copy the values into a fixed-size preallocated little-endian buffer. - // 72 bytes is enough for every scalar in this package, and having a fixed - // size lets us avoid heap allocations. - if len(a) > 72 { - panic("crypto/ecdh: internal error: isLess input too large") - } - bufA, bufB := make([]byte, 72), make([]byte, 72) - for i := range a { - bufA[i], bufB[i] = a[len(a)-i-1], b[len(b)-i-1] + return nil, err } - - // Perform a subtraction with borrow. - var borrow uint64 - for i := 0; i < len(bufA); i += 8 { - limbA, limbB := byteorder.LeUint64(bufA[i:]), byteorder.LeUint64(bufB[i:]) - _, borrow = bits.Sub64(limbA, limbB, borrow) + k := &PrivateKey{ + curve: c, + privateKey: bytes.Clone(key), + fips: fk, + publicKey: &PublicKey{ + curve: c, + publicKey: fk.PublicKey().Bytes(), + fips: fk.PublicKey(), + }, } - - // If there is a borrow at the end of the operation, then a < b. - return borrow == 1 + return k, nil } -func (c *nistCurve[Point]) NewPublicKey(key []byte) (*PublicKey, error) { +func (c *nistCurve) NewPublicKey(key []byte) (*PublicKey, error) { // Reject the point at infinity and compressed encodings. + // Note that boring.NewPublicKeyECDH would accept them. if len(key) == 0 || key[0] != 4 { return nil, errors.New("crypto/ecdh: invalid public key") } k := &PublicKey{ curve: c, - publicKey: append([]byte{}, key...), + publicKey: bytes.Clone(key), } if boring.Enabled { bk, err := boring.NewPublicKeyECDH(c.name, k.publicKey) if err != nil { - return nil, err + return nil, errors.New("crypto/ecdh: invalid public key") } k.boring = bk } else { - // SetBytes also checks that the point is on the curve. - if _, err := c.newPoint().SetBytes(key); err != nil { + fk, err := c.newPublicKey(key) + if err != nil { return nil, err } + k.fips = fk } return k, nil } -func (c *nistCurve[Point]) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { +func (c *nistCurve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { // Note that this function can't return an error, as NewPublicKey rejects // invalid points and the point at infinity, and NewPrivateKey rejects // invalid scalars and the zero value. BytesX returns an error for the point @@ -200,16 +152,7 @@ func (c *nistCurve[Point]) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, e if boring.Enabled { return boring.ECDH(local.boring, remote.boring) } - - boring.Unreachable() - p, err := c.newPoint().SetBytes(remote.publicKey) - if err != nil { - return nil, err - } - if _, err := p.ScalarMult(p, local.privateKey); err != nil { - return nil, err - } - return p.BytesX() + return c.sharedSecret(local.fips, remote.fips) } // P256 returns a [Curve] which implements NIST P-256 (FIPS 186-3, section D.2.3), @@ -219,18 +162,22 @@ func (c *nistCurve[Point]) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, e // be used for equality checks and switch statements. func P256() Curve { return p256 } -var p256 = &nistCurve[*nistec.P256Point]{ - name: "P-256", - newPoint: nistec.NewP256Point, - scalarOrder: p256Order, +var p256 = &nistCurve{ + name: "P-256", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P256(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P256(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P256(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P256(), priv, pub) + }, } -var p256Order = []byte{ - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, - 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51} - // P384 returns a [Curve] which implements NIST P-384 (FIPS 186-3, section D.2.4), // also known as secp384r1. // @@ -238,20 +185,22 @@ var p256Order = []byte{ // be used for equality checks and switch statements. func P384() Curve { return p384 } -var p384 = &nistCurve[*nistec.P384Point]{ - name: "P-384", - newPoint: nistec.NewP384Point, - scalarOrder: p384Order, +var p384 = &nistCurve{ + name: "P-384", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P384(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P384(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P384(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P384(), priv, pub) + }, } -var p384Order = []byte{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, - 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, - 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73} - // P521 returns a [Curve] which implements NIST P-521 (FIPS 186-3, section D.2.5), // also known as secp521r1. // @@ -259,18 +208,18 @@ var p384Order = []byte{ // be used for equality checks and switch statements. func P521() Curve { return p521 } -var p521 = &nistCurve[*nistec.P521Point]{ - name: "P-521", - newPoint: nistec.NewP521Point, - scalarOrder: p521Order, +var p521 = &nistCurve{ + name: "P-521", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P521(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P521(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P521(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P521(), priv, pub) + }, } - -var p521Order = []byte{0x01, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, - 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, - 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, - 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, - 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09} diff --git a/crypto/ecdh/x25519.go b/crypto/ecdh/x25519.go index 2f746ae4493..ebea50efc65 100644 --- a/crypto/ecdh/x25519.go +++ b/crypto/ecdh/x25519.go @@ -5,10 +5,12 @@ package ecdh import ( + "bytes" "errors" "io" - "github.com/runZeroInc/excrypto/crypto/internal/edwards25519/field" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/edwards25519/field" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/internal/randutil" ) @@ -34,6 +36,9 @@ func (c *x25519Curve) String() string { } func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode") + } key := make([]byte, x25519PrivateKeySize) randutil.MaybeReadByte(rand) if _, err := io.ReadFull(rand, key); err != nil { @@ -43,35 +48,35 @@ func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) { } func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode") + } if len(key) != x25519PrivateKeySize { return nil, errors.New("crypto/ecdh: invalid private key size") } + publicKey := make([]byte, x25519PublicKeySize) + x25519Basepoint := [32]byte{9} + x25519ScalarMult(publicKey, key, x25519Basepoint[:]) + // We don't check for the all-zero public key here because the scalar is + // never zero because of clamping, and the basepoint is not the identity in + // the prime-order subgroup(s). return &PrivateKey{ curve: c, - privateKey: append([]byte{}, key...), + privateKey: bytes.Clone(key), + publicKey: &PublicKey{curve: c, publicKey: publicKey}, }, nil } -func (c *x25519Curve) privateKeyToPublicKey(key *PrivateKey) *PublicKey { - if key.curve != c { - panic("crypto/ecdh: internal error: converting the wrong key type") - } - k := &PublicKey{ - curve: key.curve, - publicKey: make([]byte, x25519PublicKeySize), - } - x25519Basepoint := [32]byte{9} - x25519ScalarMult(k.publicKey, key.privateKey, x25519Basepoint[:]) - return k -} - func (c *x25519Curve) NewPublicKey(key []byte) (*PublicKey, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode") + } if len(key) != x25519PublicKeySize { return nil, errors.New("crypto/ecdh: invalid public key") } return &PublicKey{ curve: c, - publicKey: append([]byte{}, key...), + publicKey: bytes.Clone(key), }, nil } @@ -135,3 +140,12 @@ func x25519ScalarMult(dst, scalar, point []byte) { x2.Multiply(&x2, &z2) copy(dst[:], x2.Bytes()) } + +// isZero reports whether x is all zeroes in constant time. +func isZero(x []byte) bool { + var acc byte + for _, b := range x { + acc |= b + } + return acc == 0 +} diff --git a/crypto/ecdsa/boring.go b/crypto/ecdsa/boring.go new file mode 100644 index 00000000000..c8d7c90a6dc --- /dev/null +++ b/crypto/ecdsa/boring.go @@ -0,0 +1,73 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +package ecdsa + +import ( + "math/big" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/boring/bbig" +) + +type boringPub struct { + key *boring.PublicKeyECDSA + orig PublicKey +} + +func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) { + b = new(boringPub) + b.orig = copyPublicKey(pub) + key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y)) + if err != nil { + return nil, err + } + b.key = key + return key, nil +} + +type boringPriv struct { + key *boring.PrivateKeyECDSA + orig PrivateKey +} + +func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) { + b = new(boringPriv) + b.orig = copyPrivateKey(priv) + key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y), bbig.Enc(b.orig.D)) + if err != nil { + return nil, err + } + b.key = key + return key, nil +} + +func publicKeyEqual(k1, k2 *PublicKey) bool { + return k1.X != nil && + k1.Curve.Params() == k2.Curve.Params() && + k1.X.Cmp(k2.X) == 0 && + k1.Y.Cmp(k2.Y) == 0 +} + +func privateKeyEqual(k1, k2 *PrivateKey) bool { + return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && + k1.D.Cmp(k2.D) == 0 +} + +func copyPublicKey(k *PublicKey) PublicKey { + return PublicKey{ + Curve: k.Curve, + X: new(big.Int).Set(k.X), + Y: new(big.Int).Set(k.Y), + } +} + +func copyPrivateKey(k *PrivateKey) PrivateKey { + return PrivateKey{ + PublicKey: copyPublicKey(&k.PublicKey), + D: new(big.Int).Set(k.D), + } +} diff --git a/crypto/ecdsa/ecdsa.go b/crypto/ecdsa/ecdsa.go index f02dfb7a08f..9dac6ac520e 100644 --- a/crypto/ecdsa/ecdsa.go +++ b/crypto/ecdsa/ecdsa.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as -// defined in FIPS 186-4 and SEC 1, Version 2.0. +// defined in [FIPS 186-5]. // // Signatures generated by this package are not deterministic, but entropy is // mixed with the private key and the message, achieving the same level of @@ -12,36 +12,26 @@ // Operations involving private keys are implemented using constant-time // algorithms, as long as an [elliptic.Curve] returned by [elliptic.P224], // [elliptic.P256], [elliptic.P384], or [elliptic.P521] is used. -package ecdsa - -// [FIPS 186-4] references ANSI X9.62-2005 for the bulk of the ECDSA algorithm. -// That standard is not freely available, which is a problem in an open source -// implementation, because not only the implementer, but also any maintainer, -// contributor, reviewer, auditor, and learner needs access to it. Instead, this -// package references and follows the equivalent [SEC 1, Version 2.0]. // -// [FIPS 186-4]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf -// [SEC 1, Version 2.0]: https://www.secg.org/sec1-v2.pdf +// [FIPS 186-5]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf +package ecdsa import ( - "bytes" "errors" + "io" + "math/big" + "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/crypto/aes" - "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/ecdh" "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/crypto/internal/bigmod" "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/boring/bbig" - "github.com/runZeroInc/excrypto/crypto/internal/nistec" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/ecdsa" + "github.com/runZeroInc/excrypto/crypto/internal/fips140hash" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/internal/randutil" "github.com/runZeroInc/excrypto/crypto/sha512" "github.com/runZeroInc/excrypto/crypto/subtle" - "io" - "math/big" - "sync" - "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte/asn1" ) @@ -143,14 +133,24 @@ func bigIntEqual(a, b *big.Int) bool { return subtle.ConstantTimeCompare(a.Bytes(), b.Bytes()) == 1 } -// Sign signs digest with priv, reading randomness from rand. The opts argument -// is not currently used but, in keeping with the crypto.Signer interface, -// should be the hash function used to digest the message. +// Sign signs a hash (which should be the result of hashing a larger message +// with opts.HashFunc()) using the private key, priv. If the hash is longer than +// the bit-length of the private key's curve order, the hash will be truncated +// to that length. It returns the ASN.1 encoded signature, like [SignASN1]. // -// This method implements crypto.Signer, which is an interface to support keys -// where the private part is kept in, for example, a hardware module. Common -// uses can use the [SignASN1] function in this package directly. +// If rand is not nil, the signature is randomized. Most applications should use +// [crypto/rand.Reader] as rand. Note that the returned signature does not +// depend deterministically on the bytes read from rand, and may change between +// calls and/or between versions. +// +// If rand is nil, Sign will produce a deterministic signature according to RFC +// 6979. When producing a deterministic signature, opts.HashFunc() must be the +// function used to produce digest and priv.Curve must be one of +// [elliptic.P224], [elliptic.P256], [elliptic.P384], or [elliptic.P521]. func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + if rand == nil { + return signRFC6979(priv, digest, opts) + } return SignASN1(rand, priv, digest) } @@ -173,78 +173,29 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { switch c.Params() { case elliptic.P224().Params(): - return generateNISTEC(p224(), rand) + return generateFIPS(c, ecdsa.P224(), rand) case elliptic.P256().Params(): - return generateNISTEC(p256(), rand) + return generateFIPS(c, ecdsa.P256(), rand) case elliptic.P384().Params(): - return generateNISTEC(p384(), rand) + return generateFIPS(c, ecdsa.P384(), rand) case elliptic.P521().Params(): - return generateNISTEC(p521(), rand) + return generateFIPS(c, ecdsa.P521(), rand) default: return generateLegacy(c, rand) } } -func generateNISTEC[Point nistPoint[Point]](c *nistCurve[Point], rand io.Reader) (*PrivateKey, error) { - k, Q, err := randomPoint(c, rand) - if err != nil { - return nil, err +func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) { + if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { + return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") } - - priv := new(PrivateKey) - priv.PublicKey.Curve = c.curve - priv.D = new(big.Int).SetBytes(k.Bytes(c.N)) - priv.PublicKey.X, priv.PublicKey.Y, err = c.pointToAffine(Q) + privateKey, err := ecdsa.GenerateKey(c, rand) if err != nil { return nil, err } - return priv, nil -} - -// randomPoint returns a random scalar and the corresponding point using the -// procedure given in FIPS 186-4, Appendix B.5.2 (rejection sampling). -func randomPoint[Point nistPoint[Point]](c *nistCurve[Point], rand io.Reader) (k *bigmod.Nat, p Point, err error) { - k = bigmod.NewNat() - for { - b := make([]byte, c.N.Size()) - if _, err = io.ReadFull(rand, b); err != nil { - return - } - - // Mask off any excess bits to increase the chance of hitting a value in - // (0, N). These are the most dangerous lines in the package and maybe in - // the library: a single bit of bias in the selection of nonces would likely - // lead to key recovery, but no tests would fail. Look but DO NOT TOUCH. - if excess := len(b)*8 - c.N.BitLen(); excess > 0 { - // Just to be safe, assert that this only happens for the one curve that - // doesn't have a round number of bits. - if excess != 0 && c.curve.Params().Name != "P-521" { - panic("ecdsa: internal error: unexpectedly masking off bits") - } - b[0] >>= excess - } - - // FIPS 186-4 makes us check k <= N - 2 and then add one. - // Checking 0 < k <= N - 1 is strictly equivalent. - // None of this matters anyway because the chance of selecting - // zero is cryptographically negligible. - if _, err = k.SetBytes(b, c.N); err == nil && k.IsZero() == 0 { - break - } - - if testingOnlyRejectionSamplingLooped != nil { - testingOnlyRejectionSamplingLooped() - } - } - - p, err = c.newPoint().ScalarBaseMult(k.Bytes(c.N)) - return + return privateKeyFromFIPS(curve, privateKey) } -// testingOnlyRejectionSamplingLooped is called when rejection sampling in -// randomPoint rejects a candidate for being higher than the modulus. -var testingOnlyRejectionSamplingLooped func() - // errNoAsm is returned by signAsm and verifyAsm when the assembly // implementation is not available. var errNoAsm = errors.New("no assembly implementation available") @@ -269,74 +220,77 @@ func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { } boring.UnreachableExceptTests() - csprng, err := mixedCSPRNG(rand, priv, hash) - if err != nil { - return nil, err - } - - if sig, err := signAsm(priv, csprng, hash); err != errNoAsm { - return sig, err - } - switch priv.Curve.Params() { case elliptic.P224().Params(): - return signNISTEC(p224(), priv, csprng, hash) + return signFIPS(ecdsa.P224(), priv, rand, hash) case elliptic.P256().Params(): - return signNISTEC(p256(), priv, csprng, hash) + return signFIPS(ecdsa.P256(), priv, rand, hash) case elliptic.P384().Params(): - return signNISTEC(p384(), priv, csprng, hash) + return signFIPS(ecdsa.P384(), priv, rand, hash) case elliptic.P521().Params(): - return signNISTEC(p521(), priv, csprng, hash) + return signFIPS(ecdsa.P521(), priv, rand, hash) default: - return signLegacy(priv, csprng, hash) + return signLegacy(priv, rand, hash) } } -func signNISTEC[Point nistPoint[Point]](c *nistCurve[Point], priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { - // SEC 1, Version 2.0, Section 4.1.3 - - k, R, err := randomPoint(c, csprng) - if err != nil { - return nil, err +func signFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey, rand io.Reader, hash []byte) ([]byte, error) { + if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { + return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") } - - // kInv = k⁻¹ - kInv := bigmod.NewNat() - inverse(c, kInv, k) - - Rx, err := R.BytesX() + // privateKeyToFIPS is very slow in FIPS mode because it performs a + // Sign+Verify cycle per FIPS 140-3 IG 10.3.A. We should find a way to cache + // it or attach it to the PrivateKey. + k, err := privateKeyToFIPS(c, priv) if err != nil { return nil, err } - r, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) + // Always using SHA-512 instead of the hash that computed hash is + // technically a violation of draft-irtf-cfrg-det-sigs-with-noise-04 but in + // our API we don't get to know what it was, and this has no security impact. + sig, err := ecdsa.Sign(c, sha512.New, k, rand, hash) if err != nil { return nil, err } + return encodeSignature(sig.R, sig.S) +} - // The spec wants us to retry here, but the chance of hitting this condition - // on a large prime-order group like the NIST curves we support is - // cryptographically negligible. If we hit it, something is awfully wrong. - if r.IsZero() == 1 { - return nil, errors.New("ecdsa: internal error: r is zero") +func signRFC6979(priv *PrivateKey, hash []byte, opts crypto.SignerOpts) ([]byte, error) { + if opts == nil { + return nil, errors.New("ecdsa: Sign called with nil opts") } + h := opts.HashFunc() + if h.Size() != len(hash) { + return nil, errors.New("ecdsa: hash length does not match hash function") + } + switch priv.Curve.Params() { + case elliptic.P224().Params(): + return signFIPSDeterministic(ecdsa.P224(), h, priv, hash) + case elliptic.P256().Params(): + return signFIPSDeterministic(ecdsa.P256(), h, priv, hash) + case elliptic.P384().Params(): + return signFIPSDeterministic(ecdsa.P384(), h, priv, hash) + case elliptic.P521().Params(): + return signFIPSDeterministic(ecdsa.P521(), h, priv, hash) + default: + return nil, errors.New("ecdsa: curve not supported by deterministic signatures") + } +} - e := bigmod.NewNat() - hashToNat(c, e, hash) - - s, err := bigmod.NewNat().SetBytes(priv.D.Bytes(), c.N) +func signFIPSDeterministic[P ecdsa.Point[P]](c *ecdsa.Curve[P], hashFunc crypto.Hash, priv *PrivateKey, hash []byte) ([]byte, error) { + k, err := privateKeyToFIPS(c, priv) if err != nil { return nil, err } - s.Mul(r, c.N) - s.Add(e, c.N) - s.Mul(kInv, c.N) - - // Again, the chance of this happening is cryptographically negligible. - if s.IsZero() == 1 { - return nil, errors.New("ecdsa: internal error: s is zero") + h := fips140hash.UnwrapNew(hashFunc.New) + if fips140only.Enabled && !fips140only.ApprovedHash(h()) { + return nil, errors.New("crypto/ecdsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") } - - return encodeSignature(r.Bytes(c.N), s.Bytes(c.N)) + sig, err := ecdsa.SignDeterministic(c, h, k, hash) + if err != nil { + return nil, err + } + return encodeSignature(sig.R, sig.S) } func encodeSignature(r, s []byte) ([]byte, error) { @@ -366,105 +320,6 @@ func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { }) } -// inverse sets kInv to the inverse of k modulo the order of the curve. -func inverse[Point nistPoint[Point]](c *nistCurve[Point], kInv, k *bigmod.Nat) { - if c.curve.Params().Name == "P-256" { - kBytes, err := nistec.P256OrdInverse(k.Bytes(c.N)) - // Some platforms don't implement P256OrdInverse, and always return an error. - if err == nil { - _, err := kInv.SetBytes(kBytes, c.N) - if err != nil { - panic("ecdsa: internal error: P256OrdInverse produced an invalid value") - } - return - } - } - - // Calculate the inverse of s in GF(N) using Fermat's method - // (exponentiation modulo P - 2, per Euler's theorem) - kInv.Exp(k, c.nMinus2, c.N) -} - -// hashToNat sets e to the left-most bits of hash, according to -// SEC 1, Section 4.1.3, point 5 and Section 4.1.4, point 3. -func hashToNat[Point nistPoint[Point]](c *nistCurve[Point], e *bigmod.Nat, hash []byte) { - // ECDSA asks us to take the left-most log2(N) bits of hash, and use them as - // an integer modulo N. This is the absolute worst of all worlds: we still - // have to reduce, because the result might still overflow N, but to take - // the left-most bits for P-521 we have to do a right shift. - if size := c.N.Size(); len(hash) >= size { - hash = hash[:size] - if excess := len(hash)*8 - c.N.BitLen(); excess > 0 { - hash = bytes.Clone(hash) - for i := len(hash) - 1; i >= 0; i-- { - hash[i] >>= excess - if i > 0 { - hash[i] |= hash[i-1] << (8 - excess) - } - } - } - } - _, err := e.SetOverflowingBytes(hash, c.N) - if err != nil { - panic("ecdsa: internal error: truncated hash is too long") - } -} - -// mixedCSPRNG returns a CSPRNG that mixes entropy from rand with the message -// and the private key, to protect the key in case rand fails. This is -// equivalent in security to RFC 6979 deterministic nonce generation, but still -// produces randomized signatures. -func mixedCSPRNG(rand io.Reader, priv *PrivateKey, hash []byte) (io.Reader, error) { - // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: - // - // SHA2-512(priv.D || entropy || hash)[:32] - // - // The CSPRNG key is indifferentiable from a random oracle as shown in - // [Coron], the AES-CTR stream is indifferentiable from a random oracle - // under standard cryptographic assumptions (see [Larsson] for examples). - // - // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf - // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf - - // Get 256 bits of entropy from rand. - entropy := make([]byte, 32) - if _, err := io.ReadFull(rand, entropy); err != nil { - return nil, err - } - - // Initialize an SHA-512 hash context; digest... - md := sha512.New() - md.Write(priv.D.Bytes()) // the private key, - md.Write(entropy) // the entropy, - md.Write(hash) // and the input hash; - key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), - // which is an indifferentiable MAC. - - // Create an AES-CTR instance to use as a CSPRNG. - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - // Create a CSPRNG that xors a stream of zeros with - // the output of the AES-CTR instance. - const aesIV = "IV for ECDSA CTR" - return &cipher.StreamReader{ - R: zeroReader, - S: cipher.NewCTR(block, []byte(aesIV)), - }, nil -} - -type zr struct{} - -var zeroReader = zr{} - -// Read replaces the contents of dst with zeros. It is safe for concurrent use. -func (zr) Read(dst []byte) (n int, err error) { - clear(dst) - return len(dst), nil -} - // VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the // public key, pub. Its return value records whether the signature is valid. // @@ -480,75 +335,33 @@ func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { } boring.UnreachableExceptTests() - if err := verifyAsm(pub, hash, sig); err != errNoAsm { - return err == nil - } - switch pub.Curve.Params() { case elliptic.P224().Params(): - return verifyNISTEC(p224(), pub, hash, sig) + return verifyFIPS(ecdsa.P224(), pub, hash, sig) case elliptic.P256().Params(): - return verifyNISTEC(p256(), pub, hash, sig) + return verifyFIPS(ecdsa.P256(), pub, hash, sig) case elliptic.P384().Params(): - return verifyNISTEC(p384(), pub, hash, sig) + return verifyFIPS(ecdsa.P384(), pub, hash, sig) case elliptic.P521().Params(): - return verifyNISTEC(p521(), pub, hash, sig) + return verifyFIPS(ecdsa.P521(), pub, hash, sig) default: return verifyLegacy(pub, hash, sig) } } -func verifyNISTEC[Point nistPoint[Point]](c *nistCurve[Point], pub *PublicKey, hash, sig []byte) bool { - rBytes, sBytes, err := parseSignature(sig) - if err != nil { - return false - } - - Q, err := c.pointFromAffine(pub.X, pub.Y) - if err != nil { - return false - } - - // SEC 1, Version 2.0, Section 4.1.4 - - r, err := bigmod.NewNat().SetBytes(rBytes, c.N) - if err != nil || r.IsZero() == 1 { - return false - } - s, err := bigmod.NewNat().SetBytes(sBytes, c.N) - if err != nil || s.IsZero() == 1 { - return false - } - - e := bigmod.NewNat() - hashToNat(c, e, hash) - - // w = s⁻¹ - w := bigmod.NewNat() - inverse(c, w, s) - - // p₁ = [e * s⁻¹]G - p1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N)) - if err != nil { - return false - } - // p₂ = [r * s⁻¹]Q - p2, err := Q.ScalarMult(Q, w.Mul(r, c.N).Bytes(c.N)) +func verifyFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey, hash, sig []byte) bool { + r, s, err := parseSignature(sig) if err != nil { return false } - // BytesX returns an error for the point at infinity. - Rx, err := p1.Add(p1, p2).BytesX() + k, err := publicKeyToFIPS(c, pub) if err != nil { return false } - - v, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) - if err != nil { + if err := ecdsa.Verify(c, k, hash, &ecdsa.Signature{R: r, S: s}); err != nil { return false } - - return v.Equal(r) == 1 + return true } func parseSignature(sig []byte) (r, s []byte, err error) { @@ -564,32 +377,47 @@ func parseSignature(sig []byte) (r, s []byte, err error) { return r, s, nil } -type nistCurve[Point nistPoint[Point]] struct { - newPoint func() Point - curve elliptic.Curve - N *bigmod.Modulus - nMinus2 []byte +func publicKeyFromFIPS(curve elliptic.Curve, pub *ecdsa.PublicKey) (*PublicKey, error) { + x, y, err := pointToAffine(curve, pub.Bytes()) + if err != nil { + return nil, err + } + return &PublicKey{Curve: curve, X: x, Y: y}, nil } -// nistPoint is a generic constraint for the nistec Point types. -type nistPoint[T any] interface { - Bytes() []byte - BytesX() ([]byte, error) - SetBytes([]byte) (T, error) - Add(T, T) T - ScalarMult(T, []byte) (T, error) - ScalarBaseMult([]byte) (T, error) +func privateKeyFromFIPS(curve elliptic.Curve, priv *ecdsa.PrivateKey) (*PrivateKey, error) { + pub, err := publicKeyFromFIPS(curve, priv.PublicKey()) + if err != nil { + return nil, err + } + return &PrivateKey{PublicKey: *pub, D: new(big.Int).SetBytes(priv.Bytes())}, nil +} + +func publicKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey) (*ecdsa.PublicKey, error) { + Q, err := pointFromAffine(pub.Curve, pub.X, pub.Y) + if err != nil { + return nil, err + } + return ecdsa.NewPublicKey(c, Q) +} + +func privateKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) (*ecdsa.PrivateKey, error) { + Q, err := pointFromAffine(priv.Curve, priv.X, priv.Y) + if err != nil { + return nil, err + } + return ecdsa.NewPrivateKey(c, priv.D.Bytes(), Q) } -// pointFromAffine is used to convert the PublicKey to a nistec Point. -func (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, err error) { - bitSize := curve.curve.Params().BitSize +// pointFromAffine is used to convert the PublicKey to a nistec SetBytes input. +func pointFromAffine(curve elliptic.Curve, x, y *big.Int) ([]byte, error) { + bitSize := curve.Params().BitSize // Reject values that would not get correctly encoded. if x.Sign() < 0 || y.Sign() < 0 { - return p, errors.New("negative coordinate") + return nil, errors.New("negative coordinate") } if x.BitLen() > bitSize || y.BitLen() > bitSize { - return p, errors.New("overflowing coordinate") + return nil, errors.New("overflowing coordinate") } // Encode the coordinates and let SetBytes reject invalid points. byteLen := (bitSize + 7) / 8 @@ -597,81 +425,17 @@ func (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, err erro buf[0] = 4 // uncompressed point x.FillBytes(buf[1 : 1+byteLen]) y.FillBytes(buf[1+byteLen : 1+2*byteLen]) - return curve.newPoint().SetBytes(buf) + return buf, nil } -// pointToAffine is used to convert a nistec Point to a PublicKey. -func (curve *nistCurve[Point]) pointToAffine(p Point) (x, y *big.Int, err error) { - out := p.Bytes() - if len(out) == 1 && out[0] == 0 { +// pointToAffine is used to convert a nistec Bytes encoding to a PublicKey. +func pointToAffine(curve elliptic.Curve, p []byte) (x, y *big.Int, err error) { + if len(p) == 1 && p[0] == 0 { // This is the encoding of the point at infinity. return nil, nil, errors.New("ecdsa: public key point is the infinity") } - byteLen := (curve.curve.Params().BitSize + 7) / 8 - x = new(big.Int).SetBytes(out[1 : 1+byteLen]) - y = new(big.Int).SetBytes(out[1+byteLen:]) + byteLen := (curve.Params().BitSize + 7) / 8 + x = new(big.Int).SetBytes(p[1 : 1+byteLen]) + y = new(big.Int).SetBytes(p[1+byteLen:]) return x, y, nil } - -var p224Once sync.Once -var _p224 *nistCurve[*nistec.P224Point] - -func p224() *nistCurve[*nistec.P224Point] { - p224Once.Do(func() { - _p224 = &nistCurve[*nistec.P224Point]{ - newPoint: func() *nistec.P224Point { return nistec.NewP224Point() }, - } - precomputeParams(_p224, elliptic.P224()) - }) - return _p224 -} - -var p256Once sync.Once -var _p256 *nistCurve[*nistec.P256Point] - -func p256() *nistCurve[*nistec.P256Point] { - p256Once.Do(func() { - _p256 = &nistCurve[*nistec.P256Point]{ - newPoint: func() *nistec.P256Point { return nistec.NewP256Point() }, - } - precomputeParams(_p256, elliptic.P256()) - }) - return _p256 -} - -var p384Once sync.Once -var _p384 *nistCurve[*nistec.P384Point] - -func p384() *nistCurve[*nistec.P384Point] { - p384Once.Do(func() { - _p384 = &nistCurve[*nistec.P384Point]{ - newPoint: func() *nistec.P384Point { return nistec.NewP384Point() }, - } - precomputeParams(_p384, elliptic.P384()) - }) - return _p384 -} - -var p521Once sync.Once -var _p521 *nistCurve[*nistec.P521Point] - -func p521() *nistCurve[*nistec.P521Point] { - p521Once.Do(func() { - _p521 = &nistCurve[*nistec.P521Point]{ - newPoint: func() *nistec.P521Point { return nistec.NewP521Point() }, - } - precomputeParams(_p521, elliptic.P521()) - }) - return _p521 -} - -func precomputeParams[Point nistPoint[Point]](c *nistCurve[Point], curve elliptic.Curve) { - params := curve.Params() - c.curve = curve - var err error - c.N, err = bigmod.NewModulusFromBig(params.N) - if err != nil { - panic(err) - } - c.nMinus2 = new(big.Int).Sub(params.N, big.NewInt(2)).Bytes() -} diff --git a/crypto/ecdsa/ecdsa_legacy.go b/crypto/ecdsa/ecdsa_legacy.go index d6c872c6f37..0bc887fb830 100644 --- a/crypto/ecdsa/ecdsa_legacy.go +++ b/crypto/ecdsa/ecdsa_legacy.go @@ -6,10 +6,12 @@ package ecdsa import ( "errors" - "github.com/runZeroInc/excrypto/crypto/elliptic" "io" "math/big" + "math/rand/v2" + "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte/asn1" ) @@ -18,6 +20,10 @@ import ( // deprecated custom curves. func generateLegacy(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") + } + k, err := randFieldElement(c, rand) if err != nil { return nil, err @@ -75,8 +81,25 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err } func signLegacy(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { + if fips140only.Enabled { + return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") + } + c := priv.Curve + // A cheap version of hedged signatures, for the deprecated path. + var seed [32]byte + if _, err := io.ReadFull(csprng, seed[:]); err != nil { + return nil, err + } + for i, b := range priv.D.Bytes() { + seed[i%32] ^= b + } + for i, b := range hash { + seed[i%32] ^= b + } + csprng = rand.NewChaCha8(seed) + // SEC 1, Version 2.0, Section 4.1.3 N := c.Params().N if N.Sign() == 0 { @@ -130,6 +153,10 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { } func verifyLegacy(pub *PublicKey, hash []byte, sig []byte) bool { + if fips140only.Enabled { + panic("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") + } + rBytes, sBytes, err := parseSignature(sig) if err != nil { return false @@ -171,9 +198,6 @@ var one = new(big.Int).SetInt64(1) // randFieldElement returns a random element of the order of the given // curve using the procedure given in FIPS 186-4, Appendix B.5.2. func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { - // See randomPoint for notes on the algorithm. This has to match, or s390x - // signatures will come out different from other architectures, which will - // break TLS recorded tests. for { N := c.Params().N b := make([]byte, (N.BitLen()+7)/8) diff --git a/crypto/ecdsa/ecdsa_noasm.go b/crypto/ecdsa/ecdsa_noasm.go deleted file mode 100644 index e2fa8082f68..00000000000 --- a/crypto/ecdsa/ecdsa_noasm.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !s390x || purego - -package ecdsa - -import "io" - -func verifyAsm(pub *PublicKey, hash []byte, sig []byte) error { - return errNoAsm -} - -func signAsm(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { - return nil, errNoAsm -} diff --git a/crypto/ecdsa/ecdsa_s390x_test.go b/crypto/ecdsa/ecdsa_s390x_test.go deleted file mode 100644 index f8fbff152ae..00000000000 --- a/crypto/ecdsa/ecdsa_s390x_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build s390x && !purego - -package ecdsa - -import ( - "github.com/runZeroInc/excrypto/crypto/elliptic" - "testing" -) - -func TestNoAsm(t *testing.T) { - testingDisableKDSA = true - defer func() { testingDisableKDSA = false }() - - curves := [...]elliptic.Curve{ - elliptic.P256(), - elliptic.P384(), - elliptic.P521(), - } - - for _, curve := range curves { - name := curve.Params().Name - t.Run(name, func(t *testing.T) { testKeyGeneration(t, curve) }) - t.Run(name, func(t *testing.T) { testSignAndVerify(t, curve) }) - t.Run(name, func(t *testing.T) { testNonceSafety(t, curve) }) - t.Run(name, func(t *testing.T) { testINDCCA(t, curve) }) - t.Run(name, func(t *testing.T) { testNegativeInputs(t, curve) }) - } -} diff --git a/crypto/ecdsa/ecdsa_test.go b/crypto/ecdsa/ecdsa_test.go index 25a20668fb8..eba1d6ab352 100644 --- a/crypto/ecdsa/ecdsa_test.go +++ b/crypto/ecdsa/ecdsa_test.go @@ -9,17 +9,19 @@ import ( "bytes" "compress/bzip2" "encoding/hex" - "hash" "io" "math/big" "os" "strings" "testing" + "github.com/runZeroInc/excrypto/hash" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/crypto/internal/bigmod" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/sha512" @@ -41,9 +43,11 @@ func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { } for _, test := range tests { curve := test.curve - t.Run(test.name, func(t *testing.T) { - t.Parallel() - f(t, curve) + cryptotest.TestAllImplementations(t, "ecdsa", func(t *testing.T) { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) }) } } @@ -150,6 +154,15 @@ func testNonceSafety(t *testing.T, c elliptic.Curve) { } } +type readerFunc func([]byte) (int, error) + +func (f readerFunc) Read(b []byte) (int, error) { return f(b) } + +var zeroReader = readerFunc(func(b []byte) (int, error) { + clear(b) + return len(b), nil +}) + func TestINDCCA(t *testing.T) { testAllCurves(t, testINDCCA) } @@ -188,6 +201,10 @@ func fromHex(s string) *big.Int { } func TestVectors(t *testing.T) { + cryptotest.TestAllImplementations(t, "ecdsa", testVectors) +} + +func testVectors(t *testing.T) { // This test runs the full set of NIST test vectors from // https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip // @@ -341,80 +358,6 @@ func testZeroHashSignature(t *testing.T, curve elliptic.Curve) { } } -func TestRandomPoint(t *testing.T) { - t.Run("P-224", func(t *testing.T) { testRandomPoint(t, p224()) }) - t.Run("P-256", func(t *testing.T) { testRandomPoint(t, p256()) }) - t.Run("P-384", func(t *testing.T) { testRandomPoint(t, p384()) }) - t.Run("P-521", func(t *testing.T) { testRandomPoint(t, p521()) }) -} - -func testRandomPoint[Point nistPoint[Point]](t *testing.T, c *nistCurve[Point]) { - t.Cleanup(func() { testingOnlyRejectionSamplingLooped = nil }) - var loopCount int - testingOnlyRejectionSamplingLooped = func() { loopCount++ } - - // A sequence of all ones will generate 2^N-1, which should be rejected. - // (Unless, for example, we are masking too many bits.) - r := io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0xff}, 100)), rand.Reader) - if k, p, err := randomPoint(c, r); err != nil { - t.Fatal(err) - } else if k.IsZero() == 1 { - t.Error("k is zero") - } else if p.Bytes()[0] != 4 { - t.Error("p is infinity") - } - if loopCount == 0 { - t.Error("overflow was not rejected") - } - loopCount = 0 - - // A sequence of all zeroes will generate zero, which should be rejected. - r = io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0}, 100)), rand.Reader) - if k, p, err := randomPoint(c, r); err != nil { - t.Fatal(err) - } else if k.IsZero() == 1 { - t.Error("k is zero") - } else if p.Bytes()[0] != 4 { - t.Error("p is infinity") - } - if loopCount == 0 { - t.Error("zero was not rejected") - } - loopCount = 0 - - // P-256 has a 2⁻³² chance or randomly hitting a rejection. For P-224 it's - // 2⁻¹¹², for P-384 it's 2⁻¹⁹⁴, and for P-521 it's 2⁻²⁶², so if we hit in - // tests, something is horribly wrong. (For example, we are masking the - // wrong bits.) - if c.curve == elliptic.P256() { - return - } - if k, p, err := randomPoint(c, rand.Reader); err != nil { - t.Fatal(err) - } else if k.IsZero() == 1 { - t.Error("k is zero") - } else if p.Bytes()[0] != 4 { - t.Error("p is infinity") - } - if loopCount > 0 { - t.Error("unexpected rejection") - } -} - -func TestHashToNat(t *testing.T) { - t.Run("P-224", func(t *testing.T) { testHashToNat(t, p224()) }) - t.Run("P-256", func(t *testing.T) { testHashToNat(t, p256()) }) - t.Run("P-384", func(t *testing.T) { testHashToNat(t, p384()) }) - t.Run("P-521", func(t *testing.T) { testHashToNat(t, p521()) }) -} - -func testHashToNat[Point nistPoint[Point]](t *testing.T, c *nistCurve[Point]) { - for l := 0; l < 600; l++ { - h := bytes.Repeat([]byte{0xff}, l) - hashToNat(c, bigmod.NewNat(), h) - } -} - func TestZeroSignature(t *testing.T) { testAllCurves(t, testZeroSignature) } @@ -496,22 +439,113 @@ func testRMinusNSignature(t *testing.T, curve elliptic.Curve) { } } -func randomPointForCurve(curve elliptic.Curve, rand io.Reader) error { - switch curve.Params() { - case elliptic.P224().Params(): - _, _, err := randomPoint(p224(), rand) - return err - case elliptic.P256().Params(): - _, _, err := randomPoint(p256(), rand) - return err - case elliptic.P384().Params(): - _, _, err := randomPoint(p384(), rand) - return err - case elliptic.P521().Params(): - _, _, err := randomPoint(p521(), rand) - return err - default: - panic("unknown curve") +func TestRFC6979(t *testing.T) { + t.Run("P-224", func(t *testing.T) { + testRFC6979(t, elliptic.P224(), + "F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1", + "00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C", + "EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A", + "sample", + "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", + "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101") + testRFC6979(t, elliptic.P224(), + "F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1", + "00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C", + "EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A", + "test", + "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", + "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD") + }) + t.Run("P-256", func(t *testing.T) { + // This vector was bruteforced to find a message that causes the + // generation of k to loop. It was checked against + // github.com/codahale/rfc6979 (https://go.dev/play/p/FK5-fmKf7eK), + // OpenSSL 3.2.0 (https://github.com/openssl/openssl/pull/23130), + // and python-ecdsa: + // + // ecdsa.keys.SigningKey.from_secret_exponent( + // 0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721, + // ecdsa.curves.curve_by_name("NIST256p"), hashlib.sha256).sign_deterministic( + // b"wv[vnX", hashlib.sha256, lambda r, s, order: print(hex(r), hex(s))) + // + testRFC6979(t, elliptic.P256(), + "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", + "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6", + "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299", + "wv[vnX", + "EFD9073B652E76DA1B5A019C0E4A2E3FA529B035A6ABB91EF67F0ED7A1F21234", + "3DB4706C9D9F4A4FE13BB5E08EF0FAB53A57DBAB2061C83A35FA411C68D2BA33") + + // The remaining vectors are from RFC 6979. + testRFC6979(t, elliptic.P256(), + "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", + "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6", + "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299", + "sample", + "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", + "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8") + testRFC6979(t, elliptic.P256(), + "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", + "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6", + "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299", + "test", + "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", + "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083") + }) + t.Run("P-384", func(t *testing.T) { + testRFC6979(t, elliptic.P384(), + "6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5", + "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13", + "8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720", + "sample", + "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", + "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0") + testRFC6979(t, elliptic.P384(), + "6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5", + "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13", + "8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720", + "test", + "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", + "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265") + }) + t.Run("P-521", func(t *testing.T) { + testRFC6979(t, elliptic.P521(), + "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538", + "1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4", + "0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5", + "sample", + "1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", + "04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC") + testRFC6979(t, elliptic.P521(), + "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538", + "1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4", + "0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5", + "test", + "00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", + "0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86") + }) +} + +func testRFC6979(t *testing.T, curve elliptic.Curve, D, X, Y, msg, r, s string) { + priv := &PrivateKey{ + D: fromHex(D), + PublicKey: PublicKey{ + Curve: curve, + X: fromHex(X), + Y: fromHex(Y), + }, + } + h := sha256.Sum256([]byte(msg)) + sig, err := priv.Sign(nil, h[:], crypto.SHA256) + if err != nil { + t.Fatal(err) + } + expected, err := encodeSignature(fromHex(r).Bytes(), fromHex(s).Bytes()) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(sig, expected) { + t.Errorf("signature mismatch:\n got: %x\nwant: %x", sig, expected) } } diff --git a/crypto/ecdsa/example_test.go b/crypto/ecdsa/example_test.go index 1ae2cd641c3..a021d322ac4 100644 --- a/crypto/ecdsa/example_test.go +++ b/crypto/ecdsa/example_test.go @@ -7,10 +7,9 @@ package ecdsa_test import ( "fmt" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/rand" "github.com/runZeroInc/excrypto/crypto/sha256" ) diff --git a/crypto/ecdsa/notboring.go b/crypto/ecdsa/notboring.go index 3f93709067d..24f7549cb10 100644 --- a/crypto/ecdsa/notboring.go +++ b/crypto/ecdsa/notboring.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !boringcrypto + package ecdsa import "github.com/runZeroInc/excrypto/crypto/internal/boring" diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index eaa8b3fb011..72f07538101 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -16,7 +16,6 @@ package ed25519 import ( - "bytes" "errors" "io" "strconv" @@ -24,8 +23,8 @@ import ( cryptorand "crypto/rand" "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/crypto/internal/edwards25519" - "github.com/runZeroInc/excrypto/crypto/sha512" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/ed25519" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -78,7 +77,7 @@ func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds // in this package. func (priv PrivateKey) Seed() []byte { - return bytes.Clone(priv[:SeedSize]) + return append(make([]byte, 0, SeedSize), priv[:SeedSize]...) } // Sign signs the given message with priv. rand is ignored and can be nil. @@ -91,6 +90,13 @@ func (priv PrivateKey) Seed() []byte { // A value of type [Options] can be used as opts, or crypto.Hash(0) or // crypto.SHA512 directly to select plain Ed25519 or Ed25519ph, respectively. func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { + // NewPrivateKey is very slow in FIPS mode because it performs a + // Sign+Verify cycle per FIPS 140-3 IG 10.3.A. We should find a way to cache + // it or attach it to the PrivateKey. + k, err := ed25519.NewPrivateKey(priv) + if err != nil { + return nil, err + } hash := opts.HashFunc() context := "" if opts, ok := opts.(*Options); ok { @@ -98,24 +104,14 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp } switch { case hash == crypto.SHA512: // Ed25519ph - if l := len(message); l != sha512.Size { - return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) - } - if l := len(context); l > 255 { - return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) - } - signature := make([]byte, SignatureSize) - sign(signature, priv, message, domPrefixPh, context) - return signature, nil + return ed25519.SignPH(k, message, context) case hash == crypto.Hash(0) && context != "": // Ed25519ctx - if l := len(context); l > 255 { - return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) + if fips140only.Enabled { + return nil, errors.New("crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode") } - signature := make([]byte, SignatureSize) - sign(signature, priv, message, domPrefixCtx, context) - return signature, nil + return ed25519.SignCtx(k, message, context) case hash == crypto.Hash(0): // Ed25519 - return Sign(priv, message), nil + return ed25519.Sign(k, message), nil default: return nil, errors.New("ed25519: expected opts.HashFunc() zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)") } @@ -151,9 +147,7 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { } privateKey := NewKeyFromSeed(seed) - publicKey := make([]byte, PublicKeySize) - copy(publicKey, privateKey[32:]) - + publicKey := privateKey.Public().(PublicKey) return publicKey, privateKey, nil } @@ -169,21 +163,12 @@ func NewKeyFromSeed(seed []byte) PrivateKey { } func newKeyFromSeed(privateKey, seed []byte) { - if l := len(seed); l != SeedSize { - panic("ed25519: bad seed length: " + strconv.Itoa(l)) - } - - h := sha512.Sum512(seed) - s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) + k, err := ed25519.NewPrivateKeyFromSeed(seed) if err != nil { - panic("ed25519: internal error: setting scalar failed") + // NewPrivateKeyFromSeed only returns an error if the seed length is incorrect. + panic("ed25519: bad seed length: " + strconv.Itoa(len(seed))) } - A := (&edwards25519.Point{}).ScalarBaseMult(s) - - publicKey := A.Bytes() - - copy(privateKey, seed) - copy(privateKey[32:], publicKey) + copy(privateKey, k.Bytes()) } // Sign signs the message with privateKey and returns a signature. It will @@ -192,73 +177,20 @@ func Sign(privateKey PrivateKey, message []byte) []byte { // Outline the function body so that the returned signature can be // stack-allocated. signature := make([]byte, SignatureSize) - sign(signature, privateKey, message, domPrefixPure, "") + sign(signature, privateKey, message) return signature } -// Domain separation prefixes used to disambiguate Ed25519/Ed25519ph/Ed25519ctx. -// See RFC 8032, Section 2 and Section 5.1. -const ( - // domPrefixPure is empty for pure Ed25519. - domPrefixPure = "" - // domPrefixPh is dom2(phflag=1) for Ed25519ph. It must be followed by the - // uint8-length prefixed context. - domPrefixPh = "SigEd25519 no Ed25519 collisions\x01" - // domPrefixCtx is dom2(phflag=0) for Ed25519ctx. It must be followed by the - // uint8-length prefixed context. - domPrefixCtx = "SigEd25519 no Ed25519 collisions\x00" -) - -func sign(signature, privateKey, message []byte, domPrefix, context string) { - if l := len(privateKey); l != PrivateKeySize { - panic("ed25519: bad private key length: " + strconv.Itoa(l)) - } - seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:] - - h := sha512.Sum512(seed) - s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) +func sign(signature []byte, privateKey PrivateKey, message []byte) { + // NewPrivateKey is very slow in FIPS mode because it performs a + // Sign+Verify cycle per FIPS 140-3 IG 10.3.A. We should find a way to cache + // it or attach it to the PrivateKey. + k, err := ed25519.NewPrivateKey(privateKey) if err != nil { - panic("ed25519: internal error: setting scalar failed") + panic("ed25519: bad private key: " + err.Error()) } - prefix := h[32:] - - mh := sha512.New() - if domPrefix != domPrefixPure { - mh.Write([]byte(domPrefix)) - mh.Write([]byte{byte(len(context))}) - mh.Write([]byte(context)) - } - mh.Write(prefix) - mh.Write(message) - messageDigest := make([]byte, 0, sha512.Size) - messageDigest = mh.Sum(messageDigest) - r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest) - if err != nil { - panic("ed25519: internal error: setting scalar failed") - } - - R := (&edwards25519.Point{}).ScalarBaseMult(r) - - kh := sha512.New() - if domPrefix != domPrefixPure { - kh.Write([]byte(domPrefix)) - kh.Write([]byte{byte(len(context))}) - kh.Write([]byte(context)) - } - kh.Write(R.Bytes()) - kh.Write(publicKey) - kh.Write(message) - hramDigest := make([]byte, 0, sha512.Size) - hramDigest = kh.Sum(hramDigest) - k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) - if err != nil { - panic("ed25519: internal error: setting scalar failed") - } - - S := edwards25519.NewScalar().MultiplyAdd(k, s, r) - - copy(signature[:32], R.Bytes()) - copy(signature[32:], S.Bytes()) + sig := ed25519.Sign(k, message) + copy(signature, sig) } // Verify reports whether sig is a valid signature of message by publicKey. It @@ -267,7 +199,7 @@ func sign(signature, privateKey, message []byte, domPrefix, context string) { // The inputs are not considered confidential, and may leak through timing side // channels, or if an attacker has control of part of the inputs. func Verify(publicKey PublicKey, message, sig []byte) bool { - return verify(publicKey, message, sig, domPrefixPure, "") + return VerifyWithOptions(publicKey, message, sig, &Options{Hash: crypto.Hash(0)}) == nil } // VerifyWithOptions reports whether sig is a valid signature of message by @@ -282,74 +214,24 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { // The inputs are not considered confidential, and may leak through timing side // channels, or if an attacker has control of part of the inputs. func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) error { + if l := len(publicKey); l != PublicKeySize { + panic("ed25519: bad public key length: " + strconv.Itoa(l)) + } + k, err := ed25519.NewPublicKey(publicKey) + if err != nil { + return err + } switch { case opts.Hash == crypto.SHA512: // Ed25519ph - if l := len(message); l != sha512.Size { - return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) - } - if l := len(opts.Context); l > 255 { - return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) - } - if !verify(publicKey, message, sig, domPrefixPh, opts.Context) { - return errors.New("ed25519: invalid signature") - } - return nil + return ed25519.VerifyPH(k, message, sig, opts.Context) case opts.Hash == crypto.Hash(0) && opts.Context != "": // Ed25519ctx - if l := len(opts.Context); l > 255 { - return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) - } - if !verify(publicKey, message, sig, domPrefixCtx, opts.Context) { - return errors.New("ed25519: invalid signature") + if fips140only.Enabled { + return errors.New("crypto/ed25519: use of Ed25519ctx is not allowed in FIPS 140-only mode") } - return nil + return ed25519.VerifyCtx(k, message, sig, opts.Context) case opts.Hash == crypto.Hash(0): // Ed25519 - if !verify(publicKey, message, sig, domPrefixPure, "") { - return errors.New("ed25519: invalid signature") - } - return nil + return ed25519.Verify(k, message, sig) default: return errors.New("ed25519: expected opts.Hash zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)") } } - -func verify(publicKey PublicKey, message, sig []byte, domPrefix, context string) bool { - if l := len(publicKey); l != PublicKeySize { - panic("ed25519: bad public key length: " + strconv.Itoa(l)) - } - - if len(sig) != SignatureSize || sig[63]&224 != 0 { - return false - } - - A, err := (&edwards25519.Point{}).SetBytes(publicKey) - if err != nil { - return false - } - - kh := sha512.New() - if domPrefix != domPrefixPure { - kh.Write([]byte(domPrefix)) - kh.Write([]byte{byte(len(context))}) - kh.Write([]byte(context)) - } - kh.Write(sig[:32]) - kh.Write(publicKey) - kh.Write(message) - hramDigest := make([]byte, 0, sha512.Size) - hramDigest = kh.Sum(hramDigest) - k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) - if err != nil { - panic("ed25519: internal error: setting scalar failed") - } - - S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) - if err != nil { - return false - } - - // [S]B = R + [k]A --> [k](-A) + [S]B = R - minusA := (&edwards25519.Point{}).Negate(A) - R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) - - return bytes.Equal(sig[:32], R.Bytes()) -} diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go index b47e39cdb57..8c45ee057cc 100644 --- a/crypto/ed25519/ed25519_test.go +++ b/crypto/ed25519/ed25519_test.go @@ -17,9 +17,8 @@ import ( "crypto/rand" "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" "github.com/runZeroInc/excrypto/crypto/sha512" - "github.com/runZeroInc/excrypto/internal/testenv" ) func Example_ed25519ctx() { @@ -44,6 +43,56 @@ func Example_ed25519ctx() { } } +func TestGenerateKey(t *testing.T) { + // nil is like using crypto/rand.Reader. + public, private, err := GenerateKey(nil) + if err != nil { + t.Fatal(err) + } + + if len(public) != PublicKeySize { + t.Errorf("public key has the wrong size: %d", len(public)) + } + if len(private) != PrivateKeySize { + t.Errorf("private key has the wrong size: %d", len(private)) + } + if !bytes.Equal(private.Public().(PublicKey), public) { + t.Errorf("public key doesn't match private key") + } + fromSeed := NewKeyFromSeed(private.Seed()) + if !bytes.Equal(private, fromSeed) { + t.Errorf("recreating key pair from seed gave different private key") + } + + _, k2, err := GenerateKey(nil) + if err != nil { + t.Fatal(err) + } + if bytes.Equal(private, k2) { + t.Errorf("GenerateKey returned the same private key twice") + } + + _, k3, err := GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + if bytes.Equal(private, k3) { + t.Errorf("GenerateKey returned the same private key twice") + } + + // GenerateKey is documented to be the same as NewKeyFromSeed. + seed := make([]byte, SeedSize) + rand.Read(seed) + _, k4, err := GenerateKey(bytes.NewReader(seed)) + if err != nil { + t.Fatal(err) + } + k4n := NewKeyFromSeed(seed) + if !bytes.Equal(k4, k4n) { + t.Errorf("GenerateKey with seed gave different private key") + } +} + type zeroReader struct{} func (zeroReader) Read(buf []byte) (int, error) { @@ -321,11 +370,7 @@ func TestMalleability(t *testing.T) { } func TestAllocations(t *testing.T) { - if boring.Enabled { - t.Skip("skipping allocations test with BoringCrypto") - } - testenv.SkipIfOptimizationOff(t) - + cryptotest.SkipTestAllocations(t) if allocs := testing.AllocsPerRun(100, func() { seed := make([]byte, SeedSize) message := []byte("Hello, world!") diff --git a/crypto/ed25519/ed25519vectors_test.go b/crypto/ed25519/ed25519vectors_test.go index ea07118dc8d..f41f9a0697b 100644 --- a/crypto/ed25519/ed25519vectors_test.go +++ b/crypto/ed25519/ed25519vectors_test.go @@ -7,12 +7,12 @@ package ed25519_test import ( "encoding/hex" "encoding/json" - "github.com/runZeroInc/excrypto/crypto/ed25519" - "github.com/runZeroInc/excrypto/internal/testenv" "os" - "os/exec" "path/filepath" "testing" + + "github.com/runZeroInc/excrypto/crypto/ed25519" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" ) // TestEd25519Vectors runs a very large set of test vectors that exercise all @@ -72,38 +72,13 @@ func TestEd25519Vectors(t *testing.T) { } func downloadEd25519Vectors(t *testing.T) []byte { - testenv.MustHaveExternalNetwork(t) - - // Create a temp dir and modcache subdir. - d := t.TempDir() - // Create a spot for the modcache. - modcache := filepath.Join(d, "modcache") - if err := os.Mkdir(modcache, 0777); err != nil { - t.Fatal(err) - } - - t.Setenv("GO111MODULE", "on") - t.Setenv("GOMODCACHE", modcache) - // Download the JSON test file from the GOPROXY with `go mod download`, // pinning the version so test and module caching works as expected. - goTool := testenv.GoToolPath(t) - path := "filippo.io/mostly-harmless/ed25519vectors@v0.0.0-20210322192420-30a2d7243a94" - cmd := exec.Command(goTool, "mod", "download", "-modcacherw", "-json", path) - // TODO: enable the sumdb once the TryBots proxy supports it. - cmd.Env = append(os.Environ(), "GONOSUMDB=*") - output, err := cmd.Output() - if err != nil { - t.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) - } - var dm struct { - Dir string // absolute path to cached source root directory - } - if err := json.Unmarshal(output, &dm); err != nil { - t.Fatal(err) - } + path := "filippo.io/mostly-harmless/ed25519vectors" + version := "v0.0.0-20210322192420-30a2d7243a94" + dir := cryptotest.FetchModule(t, path, version) - jsonVectors, err := os.ReadFile(filepath.Join(dm.Dir, "ed25519vectors.json")) + jsonVectors, err := os.ReadFile(filepath.Join(dir, "ed25519vectors.json")) if err != nil { t.Fatalf("failed to read ed25519vectors.json: %v", err) } diff --git a/crypto/elliptic/elliptic_test.go b/crypto/elliptic/elliptic_test.go index 4ad968312fa..aedbefc4cad 100644 --- a/crypto/elliptic/elliptic_test.go +++ b/crypto/elliptic/elliptic_test.go @@ -6,11 +6,10 @@ package elliptic import ( "bytes" + "crypto/rand" "encoding/hex" "math/big" "testing" - - "crypto/rand" ) // genericParamsForCurve returns the dereferenced CurveParams for diff --git a/crypto/elliptic/nistec.go b/crypto/elliptic/nistec.go index c9aee374597..bf47658a8af 100644 --- a/crypto/elliptic/nistec.go +++ b/crypto/elliptic/nistec.go @@ -8,7 +8,7 @@ import ( "errors" "math/big" - "github.com/runZeroInc/excrypto/crypto/internal/nistec" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec" ) var p224 = &nistCurve[*nistec.P224Point]{ @@ -19,7 +19,7 @@ func initP224() { p224.params = &CurveParams{ Name: "P-224", BitSize: 224, - // FIPS 186-4, section D.1.2.2 + // SP 800-186, Section 3.2.1.2 P: bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"), N: bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"), B: bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"), @@ -28,19 +28,15 @@ func initP224() { } } -type p256Curve struct { - nistCurve[*nistec.P256Point] -} - -var p256 = &p256Curve{nistCurve[*nistec.P256Point]{ +var p256 = &nistCurve[*nistec.P256Point]{ newPoint: nistec.NewP256Point, -}} +} func initP256() { p256.params = &CurveParams{ Name: "P-256", BitSize: 256, - // FIPS 186-4, section D.1.2.3 + // SP 800-186, Section 3.2.1.3 P: bigFromDecimal("115792089210356248762697446949407573530086143415290314195533631308867097853951"), N: bigFromDecimal("115792089210356248762697446949407573529996955224135760342422259061068512044369"), B: bigFromHex("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"), @@ -57,7 +53,7 @@ func initP384() { p384.params = &CurveParams{ Name: "P-384", BitSize: 384, - // FIPS 186-4, section D.1.2.4 + // SP 800-186, Section 3.2.1.4 P: bigFromDecimal("394020061963944792122790401001436138050797392704654" + "46667948293404245721771496870329047266088258938001861606973112319"), N: bigFromDecimal("394020061963944792122790401001436138050797392704654" + @@ -79,7 +75,7 @@ func initP521() { p521.params = &CurveParams{ Name: "P-521", BitSize: 521, - // FIPS 186-4, section D.1.2.5 + // SP 800-186, Section 3.2.1.5 P: bigFromDecimal("68647976601306097149819007990813932172694353001433" + "0540939446345918554318339765605212255964066145455497729631139148" + "0858037121987999716643812574028291115057151"), @@ -229,26 +225,6 @@ func (curve *nistCurve[Point]) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int return curve.pointToAffine(p) } -// CombinedMult returns [s1]G + [s2]P where G is the generator. It's used -// through an interface upgrade in crypto/ecdsa. -func (curve *nistCurve[Point]) CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int) { - s1 = curve.normalizeScalar(s1) - q, err := curve.newPoint().ScalarBaseMult(s1) - if err != nil { - panic("crypto/elliptic: nistec rejected normalized scalar") - } - p, err := curve.pointFromAffine(Px, Py) - if err != nil { - panic("crypto/elliptic: CombinedMult was called on an invalid point") - } - s2 = curve.normalizeScalar(s2) - p, err = p.ScalarMult(p, s2) - if err != nil { - panic("crypto/elliptic: nistec rejected normalized scalar") - } - return curve.pointToAffine(p.Add(p, q)) -} - func (curve *nistCurve[Point]) Unmarshal(data []byte) (x, y *big.Int) { if len(data) == 0 || data[0] != 4 { return nil, nil diff --git a/crypto/elliptic/nistec_p256.go b/crypto/elliptic/nistec_p256.go deleted file mode 100644 index 6a505987117..00000000000 --- a/crypto/elliptic/nistec_p256.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build amd64 || arm64 - -package elliptic - -import ( - "math/big" - - "github.com/runZeroInc/excrypto/crypto/internal/nistec" -) - -func (c p256Curve) Inverse(k *big.Int) *big.Int { - if k.Sign() < 0 { - // This should never happen. - k = new(big.Int).Neg(k) - } - if k.Cmp(c.params.N) >= 0 { - // This should never happen. - k = new(big.Int).Mod(k, c.params.N) - } - scalar := k.FillBytes(make([]byte, 32)) - inverse, err := nistec.P256OrdInverse(scalar) - if err != nil { - panic("crypto/elliptic: nistec rejected normalized scalar") - } - return new(big.Int).SetBytes(inverse) -} diff --git a/crypto/elliptic/p256_test.go b/crypto/elliptic/p256_test.go index a607766bc6c..a2c2b441045 100644 --- a/crypto/elliptic/p256_test.go +++ b/crypto/elliptic/p256_test.go @@ -74,69 +74,6 @@ func TestP256Mult(t *testing.T) { } } -type synthCombinedMult struct { - Curve -} - -func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { - x1, y1 := s.ScalarBaseMult(baseScalar) - x2, y2 := s.ScalarMult(bigX, bigY, scalar) - return s.Add(x1, y1, x2, y2) -} - -func TestP256CombinedMult(t *testing.T) { - type combinedMult interface { - Curve - CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) - } - - p256, ok := P256().(combinedMult) - if !ok { - p256 = &synthCombinedMult{P256()} - } - - gx := p256.Params().Gx - gy := p256.Params().Gy - - zero := make([]byte, 32) - one := make([]byte, 32) - one[31] = 1 - two := make([]byte, 32) - two[31] = 2 - - // 0×G + 0×G = ∞ - x, y := p256.CombinedMult(gx, gy, zero, zero) - if x.Sign() != 0 || y.Sign() != 0 { - t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y) - } - - // 1×G + 0×G = G - x, y = p256.CombinedMult(gx, gy, one, zero) - if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { - t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) - } - - // 0×G + 1×G = G - x, y = p256.CombinedMult(gx, gy, zero, one) - if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { - t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) - } - - // 1×G + 1×G = 2×G - x, y = p256.CombinedMult(gx, gy, one, one) - ggx, ggy := p256.ScalarBaseMult(two) - if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 { - t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy) - } - - minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1)) - // 1×G + (-1)×G = ∞ - x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes()) - if x.Sign() != 0 || y.Sign() != 0 { - t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y) - } -} - func TestIssue52075(t *testing.T) { Gx, Gy := P256().Params().Gx, P256().Params().Gy scalar := make([]byte, 33) diff --git a/crypto/fips140/fips140.go b/crypto/fips140/fips140.go new file mode 100644 index 00000000000..a44c9771221 --- /dev/null +++ b/crypto/fips140/fips140.go @@ -0,0 +1,25 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" +) + +// Enabled reports whether the cryptography libraries are operating in FIPS +// 140-3 mode. +// +// It can be controlled at runtime using the GODEBUG setting "fips140". If set +// to "on", FIPS 140-3 mode is enabled. If set to "only", non-approved +// cryptography functions will additionally return errors or panic. +// +// This can't be changed after the program has started. +func Enabled() bool { + if fips140.Enabled && !check.Verified { + panic("crypto/fips140: FIPS 140-3 mode enabled, but integrity check didn't pass") + } + return fips140.Enabled +} diff --git a/crypto/fips140/fips140_test.go b/crypto/fips140/fips140_test.go new file mode 100644 index 00000000000..f58ed09cd30 --- /dev/null +++ b/crypto/fips140/fips140_test.go @@ -0,0 +1,52 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140 + +import ( + "os" + "testing" + + "github.com/runZeroInc/excrypto/internal/godebug" +) + +func TestImmutableGODEBUG(t *testing.T) { + defer func(v string) { os.Setenv("GODEBUG", v) }(os.Getenv("GODEBUG")) + + fips140Enabled := Enabled() + fips140Setting := godebug.New("fips140") + fips140SettingValue := fips140Setting.Value() + + os.Setenv("GODEBUG", "fips140=off") + if Enabled() != fips140Enabled { + t.Errorf("Enabled() changed after setting GODEBUG=fips140=off") + } + if fips140Setting.Value() != fips140SettingValue { + t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=off") + } + + os.Setenv("GODEBUG", "fips140=on") + if Enabled() != fips140Enabled { + t.Errorf("Enabled() changed after setting GODEBUG=fips140=on") + } + if fips140Setting.Value() != fips140SettingValue { + t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=on") + } + + os.Setenv("GODEBUG", "fips140=") + if Enabled() != fips140Enabled { + t.Errorf("Enabled() changed after setting GODEBUG=fips140=") + } + if fips140Setting.Value() != fips140SettingValue { + t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=") + } + + os.Setenv("GODEBUG", "") + if Enabled() != fips140Enabled { + t.Errorf("Enabled() changed after setting GODEBUG=") + } + if fips140Setting.Value() != fips140SettingValue { + t.Errorf("fips140Setting.Value() changed after setting GODEBUG=") + } +} diff --git a/crypto/hkdf/example_test.go b/crypto/hkdf/example_test.go new file mode 100644 index 00000000000..b6ecd00092c --- /dev/null +++ b/crypto/hkdf/example_test.go @@ -0,0 +1,54 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf_test + +import ( + "bytes" + "crypto/rand" + "fmt" + + "github.com/runZeroInc/excrypto/crypto/hkdf" + "github.com/runZeroInc/excrypto/crypto/sha256" +) + +// Usage example that expands one master secret into three other +// cryptographically secure keys. +func Example_usage() { + // Underlying hash function for HMAC. + hash := sha256.New + keyLen := hash().Size() + + // Cryptographically secure master secret. + secret := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this. + + // Non-secret salt, optional (can be nil). + // Recommended: hash-length random value. + salt := make([]byte, hash().Size()) + if _, err := rand.Read(salt); err != nil { + panic(err) + } + + // Non-secret context info, optional (can be nil). + info := "hkdf example" + + // Generate three 128-bit derived keys. + var keys [][]byte + for i := 0; i < 3; i++ { + key, err := hkdf.Key(hash, secret, salt, info, keyLen) + if err != nil { + panic(err) + } + keys = append(keys, key) + } + + for i := range keys { + fmt.Printf("Key #%d: %v\n", i+1, !bytes.Equal(keys[i], make([]byte, 16))) + } + + // Output: + // Key #1: true + // Key #2: true + // Key #3: true +} diff --git a/crypto/hkdf/hkdf.go b/crypto/hkdf/hkdf.go new file mode 100644 index 00000000000..57e2af2cb6c --- /dev/null +++ b/crypto/hkdf/hkdf.go @@ -0,0 +1,86 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation +// Function (HKDF) as defined in RFC 5869. +// +// HKDF is a cryptographic key derivation function (KDF) with the goal of +// expanding limited input keying material into one or more cryptographically +// strong secret keys. +package hkdf + +import ( + "errors" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hkdf" + "github.com/runZeroInc/excrypto/crypto/internal/fips140hash" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" +) + +// Extract generates a pseudorandom key for use with [Expand] from an input +// secret and an optional independent salt. +// +// Only use this function if you need to reuse the extracted key with multiple +// Expand invocations and different context values. Most common scenarios, +// including the generation of multiple keys, should use [Key] instead. +func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + fh := fips140hash.UnwrapNew(h) + if err := checkFIPS140Only(fh, secret); err != nil { + return nil, err + } + return hkdf.Extract(fh, secret, salt), nil +} + +// Expand derives a key from the given hash, key, and optional context info, +// returning a []byte of length keyLength that can be used as cryptographic key. +// The extraction step is skipped. +// +// The key should have been generated by [Extract], or be a uniformly +// random or pseudorandom cryptographically strong key. See RFC 5869, Section +// 3.3. Most common scenarios will want to use [Key] instead. +func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLength int) ([]byte, error) { + fh := fips140hash.UnwrapNew(h) + if err := checkFIPS140Only(fh, pseudorandomKey); err != nil { + return nil, err + } + + limit := fh().Size() * 255 + if keyLength > limit { + return nil, errors.New("hkdf: requested key length too large") + } + + return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil +} + +// Key derives a key from the given hash, secret, salt and context info, +// returning a []byte of length keyLength that can be used as cryptographic key. +// Salt and info can be nil. +func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLength int) ([]byte, error) { + fh := fips140hash.UnwrapNew(h) + if err := checkFIPS140Only(fh, secret); err != nil { + return nil, err + } + + limit := fh().Size() * 255 + if keyLength > limit { + return nil, errors.New("hkdf: requested key length too large") + } + + return hkdf.Key(fh, secret, salt, info, keyLength), nil +} + +func checkFIPS140Only[Hash hash.Hash](h func() Hash, key []byte) error { + if !fips140only.Enabled { + return nil + } + if len(key) < 112/8 { + return errors.New("crypto/hkdf: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode") + } + if !fips140only.ApprovedHash(h()) { + return errors.New("crypto/hkdf: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + return nil +} diff --git a/crypto/hkdf/hkdf_test.go b/crypto/hkdf/hkdf_test.go new file mode 100644 index 00000000000..eb3aa1a0c17 --- /dev/null +++ b/crypto/hkdf/hkdf_test.go @@ -0,0 +1,415 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf + +import ( + "bytes" + "testing" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/md5" + "github.com/runZeroInc/excrypto/crypto/sha1" + "github.com/runZeroInc/excrypto/crypto/sha256" + "github.com/runZeroInc/excrypto/crypto/sha512" +) + +type hkdfTest struct { + hash func() hash.Hash + master []byte + salt []byte + prk []byte + info []byte + out []byte +} + +var hkdfTests = []hkdfTest{ + // Tests from RFC 5869 + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, + }, + []byte{ + 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, + 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, + 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, + }, + []byte{ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, + }, + []byte{ + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65, + }, + }, + { + sha256.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + }, + []byte{ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + }, + []byte{ + 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, + 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, + 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, + }, + []byte{ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }, + []byte{ + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87, + }, + }, + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{}, + []byte{ + 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, + 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, + 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, + }, + []byte{}, + []byte{ + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8, + }, + }, + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + nil, + []byte{ + 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, + 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, + 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, + }, + nil, + []byte{ + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8, + }, + }, + { + sha1.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, + }, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, + }, + []byte{ + 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, + 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, + 0xaa, 0x2b, 0xa2, 0x43, + }, + []byte{ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, + }, + []byte{ + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96, + }, + }, + { + sha1.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + }, + []byte{ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + }, + []byte{ + 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, + 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, + 0x22, 0x4c, 0xfa, 0xf6, + }, + []byte{ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }, + []byte{ + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4, + }, + }, + { + sha1.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{}, + []byte{ + 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, + 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, + 0xa0, 0xd3, 0x2d, 0x01, + }, + []byte{}, + []byte{ + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18, + }, + }, + { + sha1.New, + []byte{ + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, + nil, + []byte{ + 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, + 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, + 0x73, 0x13, 0x85, 0xdd, + }, + nil, + []byte{ + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48, + }, + }, +} + +func TestHKDF(t *testing.T) { + for i, tt := range hkdfTests { + prk, err := Extract(tt.hash, tt.master, tt.salt) + if err != nil { + t.Errorf("test %d: PRK extraction failed: %v", i, err) + } + if !bytes.Equal(prk, tt.prk) { + t.Errorf("test %d: incorrect PRK: have %v, need %v.", i, prk, tt.prk) + } + + key, err := Key(tt.hash, tt.master, tt.salt, string(tt.info), len(tt.out)) + if err != nil { + t.Errorf("test %d: key derivation failed: %v", i, err) + } + + if !bytes.Equal(key, tt.out) { + t.Errorf("test %d: incorrect output: have %v, need %v.", i, key, tt.out) + } + + expanded, err := Expand(tt.hash, prk, string(tt.info), len(tt.out)) + if err != nil { + t.Errorf("test %d: key expansion failed: %v", i, err) + } + + if !bytes.Equal(expanded, tt.out) { + t.Errorf("test %d: incorrect output from Expand: have %v, need %v.", i, expanded, tt.out) + } + } +} + +func TestHKDFLimit(t *testing.T) { + hash := sha1.New + master := []byte{0x00, 0x01, 0x02, 0x03} + info := "" + limit := hash().Size() * 255 + + // The maximum output bytes should be extractable + out, err := Key(hash, master, nil, info, limit) + if err != nil || len(out) != limit { + t.Errorf("key derivation failed: %v", err) + } + + // Reading one more should return an error + _, err = Key(hash, master, nil, info, limit+1) + if err == nil { + t.Error("expected key derivation to fail, but it succeeded") + } +} + +func Benchmark16ByteMD5Single(b *testing.B) { + benchmarkHKDF(md5.New, 16, b) +} + +func Benchmark20ByteSHA1Single(b *testing.B) { + benchmarkHKDF(sha1.New, 20, b) +} + +func Benchmark32ByteSHA256Single(b *testing.B) { + benchmarkHKDF(sha256.New, 32, b) +} + +func Benchmark64ByteSHA512Single(b *testing.B) { + benchmarkHKDF(sha512.New, 64, b) +} + +func benchmarkHKDF(hasher func() hash.Hash, block int, b *testing.B) { + master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} + salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} + info := string([]byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}) + + b.SetBytes(int64(block)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err := Key(hasher, master, salt, info, hasher().Size()) + if err != nil { + b.Errorf("failed to derive key: %v", err) + } + } +} + +func TestFIPSServiceIndicator(t *testing.T) { + if boring.Enabled { + t.Skip("in BoringCrypto mode HMAC is not from the Go FIPS module") + } + + fips140.ResetServiceIndicator() + _, err := Key(sha256.New, []byte("YELLOW SUBMARINE"), nil, "", 32) + if err != nil { + panic(err) + } + if !fips140.ServiceIndicator() { + t.Error("FIPS service indicator should be set") + } + + // Key too short. + fips140.ResetServiceIndicator() + _, err = Key(sha256.New, []byte("key"), nil, "", 32) + if err != nil { + panic(err) + } + if fips140.ServiceIndicator() { + t.Error("FIPS service indicator should not be set") + } + + // Salt and info are short, which is ok, but translates to a short HMAC key. + fips140.ResetServiceIndicator() + _, err = Key(sha256.New, []byte("YELLOW SUBMARINE"), []byte("salt"), "info", 32) + if err != nil { + panic(err) + } + if !fips140.ServiceIndicator() { + t.Error("FIPS service indicator should be set") + } +} diff --git a/crypto/hmac/hmac.go b/crypto/hmac/hmac.go index 55433fcab22..7b713ecae5d 100644 --- a/crypto/hmac/hmac.go +++ b/crypto/hmac/hmac.go @@ -22,107 +22,17 @@ timing side-channels: package hmac import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac" + "github.com/runZeroInc/excrypto/crypto/internal/fips140hash" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/subtle" ) -// FIPS 198-1: -// https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf - -// key is zero padded to the block size of the hash function -// ipad = 0x36 byte repeated for key length -// opad = 0x5c byte repeated for key length -// hmac = H([key ^ opad] H([key ^ ipad] text)) - -// marshalable is the combination of encoding.BinaryMarshaler and -// encoding.BinaryUnmarshaler. Their method definitions are repeated here to -// avoid a dependency on the encoding package. -type marshalable interface { - MarshalBinary() ([]byte, error) - UnmarshalBinary([]byte) error -} - -type hmac struct { - opad, ipad []byte - outer, inner hash.Hash - - // If marshaled is true, then opad and ipad do not contain a padded - // copy of the key, but rather the marshaled state of outer/inner after - // opad/ipad has been fed into it. - marshaled bool -} - -func (h *hmac) Sum(in []byte) []byte { - origLen := len(in) - in = h.inner.Sum(in) - - if h.marshaled { - if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil { - panic(err) - } - } else { - h.outer.Reset() - h.outer.Write(h.opad) - } - h.outer.Write(in[origLen:]) - return h.outer.Sum(in[:origLen]) -} - -func (h *hmac) Write(p []byte) (n int, err error) { - return h.inner.Write(p) -} - -func (h *hmac) Size() int { return h.outer.Size() } -func (h *hmac) BlockSize() int { return h.inner.BlockSize() } - -func (h *hmac) Reset() { - if h.marshaled { - if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil { - panic(err) - } - return - } - - h.inner.Reset() - h.inner.Write(h.ipad) - - // If the underlying hash is marshalable, we can save some time by - // saving a copy of the hash state now, and restoring it on future - // calls to Reset and Sum instead of writing ipad/opad every time. - // - // If either hash is unmarshalable for whatever reason, - // it's safe to bail out here. - marshalableInner, innerOK := h.inner.(marshalable) - if !innerOK { - return - } - marshalableOuter, outerOK := h.outer.(marshalable) - if !outerOK { - return - } - - imarshal, err := marshalableInner.MarshalBinary() - if err != nil { - return - } - - h.outer.Reset() - h.outer.Write(h.opad) - omarshal, err := marshalableOuter.MarshalBinary() - if err != nil { - return - } - - // Marshaling succeeded; save the marshaled state for later - h.ipad = imarshal - h.opad = omarshal - h.marshaled = true -} - // New returns a new HMAC hash using the given [hash.Hash] type and key. -// New functions like sha256.New from [crypto/sha256] can be used as h. +// New functions like [crypto/sha256.New] can be used as h. // h must return a new Hash every time it is called. // Note that unlike other hash implementations in the standard library, // the returned Hash does not implement [encoding.BinaryMarshaler] @@ -135,41 +45,16 @@ func New(h func() hash.Hash, key []byte) hash.Hash { } // BoringCrypto did not recognize h, so fall through to standard Go code. } - hm := new(hmac) - hm.outer = h() - hm.inner = h() - unique := true - func() { - defer func() { - // The comparison might panic if the underlying types are not comparable. - _ = recover() - }() - if hm.outer == hm.inner { - unique = false + h = fips140hash.UnwrapNew(h) + if fips140only.Enabled { + if len(key) < 112/8 { + panic("crypto/hmac: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode") + } + if !fips140only.ApprovedHash(h()) { + panic("crypto/hmac: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") } - }() - if !unique { - panic("crypto/hmac: hash generation function does not produce unique values") - } - blocksize := hm.inner.BlockSize() - hm.ipad = make([]byte, blocksize) - hm.opad = make([]byte, blocksize) - if len(key) > blocksize { - // If key is too big, hash it. - hm.outer.Write(key) - key = hm.outer.Sum(nil) - } - copy(hm.ipad, key) - copy(hm.opad, key) - for i := range hm.ipad { - hm.ipad[i] ^= 0x36 - } - for i := range hm.opad { - hm.opad[i] ^= 0x5c } - hm.inner.Write(hm.ipad) - - return hm + return hmac.New(h, key) } // Equal compares two MACs for equality without leaking timing information. diff --git a/crypto/hmac/hmac_test.go b/crypto/hmac/hmac_test.go index 9c08adde8d3..7b4e143ef03 100644 --- a/crypto/hmac/hmac_test.go +++ b/crypto/hmac/hmac_test.go @@ -5,15 +5,18 @@ package hmac import ( + "errors" "fmt" + "testing" + + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" "github.com/runZeroInc/excrypto/crypto/md5" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/sha512" - "hash" - "testing" ) type hmacTest struct { @@ -583,6 +586,18 @@ func TestHMAC(t *testing.T) { } } +func TestNoClone(t *testing.T) { + h := New(func() hash.Hash { return justHash{sha256.New()} }, []byte("key")) + if _, ok := h.(hash.Cloner); !ok { + t.Skip("no Cloner support") + } + h.Write([]byte("test")) + _, err := h.(hash.Cloner).Clone() + if !errors.Is(err, errors.ErrUnsupported) { + t.Errorf("Clone() = %v, want ErrUnsupported", err) + } +} + func TestNonUniqueHash(t *testing.T) { if boring.Enabled { t.Skip("hash.Hash provided by boringcrypto are not comparable") @@ -632,6 +647,18 @@ func TestHMACHash(t *testing.T) { } } +func TestExtraMethods(t *testing.T) { + h := New(sha256.New, []byte("key")) + cryptotest.NoExtraMethods(t, maybeCloner(h)) +} + +func maybeCloner(h hash.Hash) any { + if c, ok := h.(hash.Cloner); ok { + return &c + } + return &h +} + func BenchmarkHMACSHA256_1K(b *testing.B) { key := make([]byte, 32) buf := make([]byte, 1024) diff --git a/crypto/internal/alias/alias_test.go b/crypto/internal/alias/alias_test.go deleted file mode 100644 index a68fb33667b..00000000000 --- a/crypto/internal/alias/alias_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package alias - -import "testing" - -var a, b [100]byte - -var aliasingTests = []struct { - x, y []byte - anyOverlap, inexactOverlap bool -}{ - {a[:], b[:], false, false}, - {a[:], b[:0], false, false}, - {a[:], b[:50], false, false}, - {a[40:50], a[50:60], false, false}, - {a[40:50], a[60:70], false, false}, - {a[:51], a[50:], true, true}, - {a[:], a[:], true, false}, - {a[:50], a[:60], true, false}, - {a[:], nil, false, false}, - {nil, nil, false, false}, - {a[:], a[:0], false, false}, - {a[:10], a[:10:20], true, false}, - {a[:10], a[5:10:20], true, true}, -} - -func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { - any := AnyOverlap(x, y) - if any != anyOverlap { - t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) - } - inexact := InexactOverlap(x, y) - if inexact != inexactOverlap { - t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) - } -} - -func TestAliasing(t *testing.T) { - for i, tt := range aliasingTests { - testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) - testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) - } -} diff --git a/crypto/internal/bigmod/_asm/go.mod b/crypto/internal/bigmod/_asm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/bigmod/_asm/go.sum b/crypto/internal/bigmod/_asm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/boring/Dockerfile b/crypto/internal/boring/Dockerfile new file mode 100644 index 00000000000..263692b288a --- /dev/null +++ b/crypto/internal/boring/Dockerfile @@ -0,0 +1,82 @@ +# Copyright 2020 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Run this using build.sh. + +ARG ubuntu=ubuntu +FROM $ubuntu:focal + +RUN mkdir /boring +WORKDIR /boring + +ENV LANG=C +ENV LANGUAGE= + +# Following the Security Policy for FIPS 140 certificate #4735. +# https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp4735.pdf +# This corresponds to boringssl.googlesource.com/boringssl tag fips-20220613. +RUN apt-get update && \ + apt-get install --no-install-recommends -y xz-utils wget unzip ca-certificates python lsb-release software-properties-common gnupg make libssl-dev faketime + +# Install Clang. +ENV ClangV=14 +RUN \ + wget https://apt.llvm.org/llvm.sh && \ + chmod +x llvm.sh && \ + ./llvm.sh $ClangV + +# Download, validate, unpack, build, and install Ninja. +ENV NinjaV=1.10.2 +ENV NinjaH=ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed +RUN \ + wget https://github.com/ninja-build/ninja/archive/refs/tags/v$NinjaV.tar.gz && \ + echo "$NinjaH v$NinjaV.tar.gz" >sha && sha256sum -c sha && \ + tar -xzf v$NinjaV.tar.gz && \ + rm v$NinjaV.tar.gz && \ + cd ninja-$NinjaV && \ + CC=clang-$ClangV CXX=clang++-$ClangV ./configure.py --bootstrap && \ + mv ninja /usr/local/bin/ + +# Download, validate, unpack, build, and install Cmake. +ENV CmakeV=3.22.1 +ENV CmakeH=0e998229549d7b3f368703d20e248e7ee1f853910d42704aa87918c213ea82c0 +RUN \ + wget https://github.com/Kitware/CMake/releases/download/v$CmakeV/cmake-$CmakeV.tar.gz && \ + echo "$CmakeH cmake-$CmakeV.tar.gz" >sha && sha256sum -c sha && \ + tar -xzf cmake-$CmakeV.tar.gz && \ + rm cmake-$CmakeV.tar.gz && \ + cd cmake-$CmakeV && \ + CC=clang-$ClangV CXX=clang++-$ClangV ./bootstrap && \ + make && make install + +# Download, validate, unpack, and install Go. +ARG GOARCH +ENV GoV=1.18.1 +ENV GoHamd64=b3b815f47ababac13810fc6021eb73d65478e0b2db4b09d348eefad9581a2334 +ENV GoHarm64=56a91851c97fb4697077abbca38860f735c32b38993ff79b088dac46e4735633 +RUN \ + eval GoH=\${GoH$GOARCH} && \ + wget https://golang.org/dl/go$GoV.linux-$GOARCH.tar.gz && \ + echo "$GoH go$GoV.linux-$GOARCH.tar.gz" >sha && sha256sum -c sha && \ + tar -C /usr/local -xzf go$GoV.linux-$GOARCH.tar.gz && \ + rm go$GoV.linux-$GOARCH.tar.gz && \ + ln -s /usr/local/go/bin/go /usr/local/bin/ + +# Download, validate, and unpack BoringCrypto. +ENV BoringV=0c6f40132b828e92ba365c6b7680e32820c63fa7 +ENV BoringH=62f733289f2d677c2723f556aa58034c438f3a7bbca6c12b156538a88e38da8a +RUN \ + wget https://commondatastorage.googleapis.com/chromium-boringssl-fips/boringssl-$BoringV.tar.xz && \ + echo "$BoringH boringssl-$BoringV.tar.xz" >sha && sha256sum -c sha && \ + tar xJf boringssl-$BoringV.tar.xz + +# Build BoringCrypto. +ADD build-boring.sh /boring/build-boring.sh +RUN /boring/build-boring.sh + +# Build Go BoringCrypto syso. +# build.sh copies it back out of the Docker image. +ADD goboringcrypto.h /boring/godriver/goboringcrypto.h +ADD build-goboring.sh /boring/build-goboring.sh +RUN /boring/build-goboring.sh diff --git a/crypto/internal/boring/LICENSE b/crypto/internal/boring/LICENSE new file mode 100644 index 00000000000..05b0963f5e3 --- /dev/null +++ b/crypto/internal/boring/LICENSE @@ -0,0 +1,202 @@ +The Go source code and supporting files in this directory +are covered by the usual Go license (see ../../../../LICENSE). + +When building with GOEXPERIMENT=boringcrypto, the following applies. + +The goboringcrypto_linux_amd64.syso object file is built +from BoringSSL source code by build/build.sh and is covered +by the BoringSSL license reproduced below and also at +https://boringssl.googlesource.com/boringssl/+/fips-20220613/LICENSE. + +BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL +licensing. Files that are completely new have a Google copyright and an ISC +license. This license is reproduced at the bottom of this file. + +Contributors to BoringSSL are required to follow the CLA rules for Chromium: +https://cla.developers.google.com/clas + +Some files from Intel are under yet another license, which is also included +underneath. + +The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the +OpenSSL License and the original SSLeay license apply to the toolkit. See below +for the actual license texts. Actually both licenses are BSD-style Open Source +licenses. In case of any license issues related to OpenSSL please contact +openssl-core@openssl.org. + +The following are Google-internal bug numbers where explicit permission from +some authors is recorded for use of their work. (This is purely for our own +record keeping.) + 27287199 + 27287880 + 27287883 + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + +ISC license used for completely new code in BoringSSL: + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +Some files from Intel carry the following license: + +# Copyright (c) 2012, Intel Corporation +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# +# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/crypto/internal/boring/README.md b/crypto/internal/boring/README.md new file mode 100644 index 00000000000..62106cdc706 --- /dev/null +++ b/crypto/internal/boring/README.md @@ -0,0 +1,40 @@ +We have been working inside Google on a fork of Go that uses +BoringCrypto (the core of [BoringSSL](https://boringssl.googlesource.com/boringssl/)) +for various crypto primitives, in furtherance of some work related to FIPS 140. +We have heard that some external users of Go would be +interested in this code as well, so we have published this code +here in the main Go repository behind the setting GOEXPERIMENT=boringcrypto. + +Use of GOEXPERIMENT=boringcrypto outside Google is _unsupported_. +This mode is not part of the [Go 1 compatibility rules](https://go.dev/doc/go1compat), +and it may change incompatibly or break in other ways at any time. + +To be clear, we are not making any statements or representations about +the suitability of this code in relation to the FIPS 140 standard. +Interested users will have to evaluate for themselves whether the code +is useful for their own purposes. + +--- + +This directory holds the core of the BoringCrypto implementation +as well as the build scripts for the module itself: syso/*.syso. + +syso/goboringcrypto_linux_amd64.syso is built with: + + GOARCH=amd64 ./build.sh + +syso/goboringcrypto_linux_arm64.syso is built with: + + GOARCH=arm64 ./build.sh + +Both run using Docker. + +For the arm64 build to run on an x86 system, you need + + apt-get install qemu-user-static qemu-binfmt-support + +to allow the x86 kernel to run arm64 binaries via QEMU. + +For the amd64 build to run on an Apple Silicon macOS, you need Rosetta 2. + +See build.sh for more details about the build. diff --git a/crypto/internal/boring/aes.go b/crypto/internal/boring/aes.go new file mode 100644 index 00000000000..f19b6b713bd --- /dev/null +++ b/crypto/internal/boring/aes.go @@ -0,0 +1,401 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +/* + +#include "goboringcrypto.h" + +// These wrappers allocate out_len on the C stack, and check that it matches the expected +// value, to avoid having to pass a pointer from Go, which would escape to the heap. + +int EVP_AEAD_CTX_seal_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out, + size_t exp_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + size_t out_len; + int ok = _goboringcrypto_EVP_AEAD_CTX_seal(ctx, out, &out_len, exp_out_len, + nonce, nonce_len, in, in_len, ad, ad_len); + if (out_len != exp_out_len) { + return 0; + } + return ok; +}; + +int EVP_AEAD_CTX_open_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out, + size_t exp_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + size_t out_len; + int ok = _goboringcrypto_EVP_AEAD_CTX_open(ctx, out, &out_len, exp_out_len, + nonce, nonce_len, in, in_len, ad, ad_len); + if (out_len != exp_out_len) { + return 0; + } + return ok; +}; + +*/ +import "C" +import ( + "bytes" + "errors" + "runtime" + "strconv" + "unsafe" + + "github.com/runZeroInc/excrypto/crypto/cipher" +) + +type aesKeySizeError int + +func (k aesKeySizeError) Error() string { + return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) +} + +const aesBlockSize = 16 + +type aesCipher struct { + key []byte + enc C.GO_AES_KEY + dec C.GO_AES_KEY +} + +type extraModes interface { + // Copied out of crypto/aes/modes.go. + NewCBCEncrypter(iv []byte) cipher.BlockMode + NewCBCDecrypter(iv []byte) cipher.BlockMode + NewCTR(iv []byte) cipher.Stream + NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) +} + +var _ extraModes = (*aesCipher)(nil) + +func NewAESCipher(key []byte) (cipher.Block, error) { + c := &aesCipher{key: bytes.Clone(key)} + // Note: 0 is success, contradicting the usual BoringCrypto convention. + if C._goboringcrypto_AES_set_decrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.dec) != 0 || + C._goboringcrypto_AES_set_encrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.enc) != 0 { + return nil, aesKeySizeError(len(key)) + } + return c, nil +} + +func (c *aesCipher) BlockSize() int { return aesBlockSize } + +func (c *aesCipher) Encrypt(dst, src []byte) { + if inexactOverlap(dst, src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(src) < aesBlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < aesBlockSize { + panic("crypto/aes: output not full block") + } + C._goboringcrypto_AES_encrypt( + (*C.uint8_t)(unsafe.Pointer(&src[0])), + (*C.uint8_t)(unsafe.Pointer(&dst[0])), + &c.enc) +} + +func (c *aesCipher) Decrypt(dst, src []byte) { + if inexactOverlap(dst, src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(src) < aesBlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < aesBlockSize { + panic("crypto/aes: output not full block") + } + C._goboringcrypto_AES_decrypt( + (*C.uint8_t)(unsafe.Pointer(&src[0])), + (*C.uint8_t)(unsafe.Pointer(&dst[0])), + &c.dec) +} + +type aesCBC struct { + key *C.GO_AES_KEY + mode C.int + iv [aesBlockSize]byte +} + +func (x *aesCBC) BlockSize() int { return aesBlockSize } + +func (x *aesCBC) CryptBlocks(dst, src []byte) { + if inexactOverlap(dst, src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(src)%aesBlockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if len(src) > 0 { + C._goboringcrypto_AES_cbc_encrypt( + (*C.uint8_t)(unsafe.Pointer(&src[0])), + (*C.uint8_t)(unsafe.Pointer(&dst[0])), + C.size_t(len(src)), x.key, + (*C.uint8_t)(unsafe.Pointer(&x.iv[0])), x.mode) + } +} + +func (x *aesCBC) SetIV(iv []byte) { + if len(iv) != aesBlockSize { + panic("cipher: incorrect length IV") + } + copy(x.iv[:], iv) +} + +func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode { + x := &aesCBC{key: &c.enc, mode: C.GO_AES_ENCRYPT} + copy(x.iv[:], iv) + return x +} + +func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { + x := &aesCBC{key: &c.dec, mode: C.GO_AES_DECRYPT} + copy(x.iv[:], iv) + return x +} + +type aesCTR struct { + key *C.GO_AES_KEY + iv [aesBlockSize]byte + num C.uint + ecount_buf [16]C.uint8_t +} + +func (x *aesCTR) XORKeyStream(dst, src []byte) { + if inexactOverlap(dst, src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if len(src) == 0 { + return + } + C._goboringcrypto_AES_ctr128_encrypt( + (*C.uint8_t)(unsafe.Pointer(&src[0])), + (*C.uint8_t)(unsafe.Pointer(&dst[0])), + C.size_t(len(src)), x.key, (*C.uint8_t)(unsafe.Pointer(&x.iv[0])), + &x.ecount_buf[0], &x.num) +} + +func (c *aesCipher) NewCTR(iv []byte) cipher.Stream { + x := &aesCTR{key: &c.enc} + copy(x.iv[:], iv) + return x +} + +type aesGCM struct { + ctx C.GO_EVP_AEAD_CTX + aead *C.GO_EVP_AEAD +} + +const ( + gcmBlockSize = 16 + gcmTagSize = 16 + gcmStandardNonceSize = 12 +) + +type aesNonceSizeError int + +func (n aesNonceSizeError) Error() string { + return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n)) +} + +type noGCM struct { + cipher.Block +} + +func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { + if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize { + return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time") + } + // Fall back to standard library for GCM with non-standard nonce or tag size. + if nonceSize != gcmStandardNonceSize { + return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize) + } + if tagSize != gcmTagSize { + return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) + } + return c.newGCM(0) +} + +const ( + VersionTLS12 = 0x0303 + VersionTLS13 = 0x0304 +) + +func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { + return c.(*aesCipher).newGCM(VersionTLS12) +} + +func NewGCMTLS13(c cipher.Block) (cipher.AEAD, error) { + return c.(*aesCipher).newGCM(VersionTLS13) +} + +func (c *aesCipher) newGCM(tlsVersion uint16) (cipher.AEAD, error) { + var aead *C.GO_EVP_AEAD + switch len(c.key) * 8 { + case 128: + switch tlsVersion { + case VersionTLS12: + aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12() + case VersionTLS13: + aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls13() + default: + aead = C._goboringcrypto_EVP_aead_aes_128_gcm() + } + case 256: + switch tlsVersion { + case VersionTLS12: + aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12() + case VersionTLS13: + aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls13() + default: + aead = C._goboringcrypto_EVP_aead_aes_256_gcm() + } + default: + // Fall back to standard library for GCM with non-standard key size. + return cipher.NewGCMWithNonceSize(&noGCM{c}, gcmStandardNonceSize) + } + + g := &aesGCM{aead: aead} + if C._goboringcrypto_EVP_AEAD_CTX_init(&g.ctx, aead, (*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.size_t(len(c.key)), C.GO_EVP_AEAD_DEFAULT_TAG_LENGTH, nil) == 0 { + return nil, fail("EVP_AEAD_CTX_init") + } + // Note: Because of the finalizer, any time g.ctx is passed to cgo, + // that call must be followed by a call to runtime.KeepAlive(g), + // to make sure g is not collected (and finalized) before the cgo + // call returns. + runtime.SetFinalizer(g, (*aesGCM).finalize) + if g.NonceSize() != gcmStandardNonceSize { + panic("boringcrypto: internal confusion about nonce size") + } + if g.Overhead() != gcmTagSize { + panic("boringcrypto: internal confusion about tag size") + } + + return g, nil +} + +func (g *aesGCM) finalize() { + C._goboringcrypto_EVP_AEAD_CTX_cleanup(&g.ctx) +} + +func (g *aesGCM) NonceSize() int { + return int(C._goboringcrypto_EVP_AEAD_nonce_length(g.aead)) +} + +func (g *aesGCM) Overhead() int { + return int(C._goboringcrypto_EVP_AEAD_max_overhead(g.aead)) +} + +// base returns the address of the underlying array in b, +// being careful not to panic when b has zero length. +func base(b []byte) *C.uint8_t { + if len(b) == 0 { + return nil + } + return (*C.uint8_t)(unsafe.Pointer(&b[0])) +} + +func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != gcmStandardNonceSize { + panic("cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) { + panic("cipher: message too large for GCM") + } + if len(dst)+len(plaintext)+gcmTagSize < len(dst) { + panic("cipher: message too large for buffer") + } + + // Make room in dst to append plaintext+overhead. + n := len(dst) + for cap(dst) < n+len(plaintext)+gcmTagSize { + dst = append(dst[:cap(dst)], 0) + } + dst = dst[:n+len(plaintext)+gcmTagSize] + + // Check delayed until now to make sure len(dst) is accurate. + if inexactOverlap(dst[n:], plaintext) { + panic("cipher: invalid buffer overlap") + } + + outLen := C.size_t(len(plaintext) + gcmTagSize) + ok := C.EVP_AEAD_CTX_seal_wrapper( + &g.ctx, + (*C.uint8_t)(unsafe.Pointer(&dst[n])), outLen, + base(nonce), C.size_t(len(nonce)), + base(plaintext), C.size_t(len(plaintext)), + base(additionalData), C.size_t(len(additionalData))) + runtime.KeepAlive(g) + if ok == 0 { + panic(fail("EVP_AEAD_CTX_seal")) + } + return dst[:n+int(outLen)] +} + +var errOpen = errors.New("cipher: message authentication failed") + +func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != gcmStandardNonceSize { + panic("cipher: incorrect nonce length given to GCM") + } + if len(ciphertext) < gcmTagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize { + return nil, errOpen + } + + // Make room in dst to append ciphertext without tag. + n := len(dst) + for cap(dst) < n+len(ciphertext)-gcmTagSize { + dst = append(dst[:cap(dst)], 0) + } + dst = dst[:n+len(ciphertext)-gcmTagSize] + + // Check delayed until now to make sure len(dst) is accurate. + if inexactOverlap(dst[n:], ciphertext) { + panic("cipher: invalid buffer overlap") + } + + outLen := C.size_t(len(ciphertext) - gcmTagSize) + ok := C.EVP_AEAD_CTX_open_wrapper( + &g.ctx, + base(dst[n:]), outLen, + base(nonce), C.size_t(len(nonce)), + base(ciphertext), C.size_t(len(ciphertext)), + base(additionalData), C.size_t(len(additionalData))) + runtime.KeepAlive(g) + if ok == 0 { + return nil, errOpen + } + return dst[:n+int(outLen)], nil +} + +func anyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +func inexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return anyOverlap(x, y) +} diff --git a/crypto/internal/boring/bbig/big.go b/crypto/internal/boring/bbig/big.go index fb3bf762f12..002246ec41f 100644 --- a/crypto/internal/boring/bbig/big.go +++ b/crypto/internal/boring/bbig/big.go @@ -5,9 +5,10 @@ package bbig import ( - "github.com/runZeroInc/excrypto/crypto/internal/boring" "math/big" "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" ) func Enc(b *big.Int) boring.BigInt { diff --git a/crypto/internal/boring/boring.go b/crypto/internal/boring/boring.go new file mode 100644 index 00000000000..9f24fc17413 --- /dev/null +++ b/crypto/internal/boring/boring.go @@ -0,0 +1,131 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +/* +// goboringcrypto_linux_amd64.syso references pthread functions. +#cgo LDFLAGS: "-pthread" + +#include "goboringcrypto.h" +*/ +import "C" +import ( + "math/bits" + "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/boring/sig" + _ "github.com/runZeroInc/excrypto/crypto/internal/boring/syso" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/internal/stringslite" +) + +const available = true + +func init() { + C._goboringcrypto_BORINGSSL_bcm_power_on_self_test() + if C._goboringcrypto_FIPS_mode() != 1 { + panic("boringcrypto: not in FIPS mode") + } + sig.BoringCrypto() +} + +func init() { + if fips140.Enabled { + panic("boringcrypto: cannot use GODEBUG=fips140 with GOEXPERIMENT=boringcrypto") + } +} + +// Unreachable marks code that should be unreachable +// when BoringCrypto is in use. It panics. +func Unreachable() { + panic("boringcrypto: invalid code execution") +} + +// provided by runtime to avoid os import. +func runtime_arg0() string + +// UnreachableExceptTests marks code that should be unreachable +// when BoringCrypto is in use. It panics. +func UnreachableExceptTests() { + name := runtime_arg0() + // If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well. + if !stringslite.HasSuffix(name, "_test") && !stringslite.HasSuffix(name, ".test") { + println("boringcrypto: unexpected code execution in", name) + panic("boringcrypto: invalid code execution") + } +} + +type fail string + +func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" } + +func wbase(b BigInt) *C.uint8_t { + if len(b) == 0 { + return nil + } + return (*C.uint8_t)(unsafe.Pointer(&b[0])) +} + +const wordBytes = bits.UintSize / 8 + +func bigToBN(x BigInt) *C.GO_BIGNUM { + return C._goboringcrypto_BN_le2bn(wbase(x), C.size_t(len(x)*wordBytes), nil) +} + +func bytesToBN(x []byte) *C.GO_BIGNUM { + return C._goboringcrypto_BN_bin2bn((*C.uint8_t)(&x[0]), C.size_t(len(x)), nil) +} + +func bnToBig(bn *C.GO_BIGNUM) BigInt { + x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes) + if C._goboringcrypto_BN_bn2le_padded(wbase(x), C.size_t(len(x)*wordBytes), bn) == 0 { + panic("boringcrypto: bignum conversion failed") + } + return x +} + +func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool { + if *bnp != nil { + C._goboringcrypto_BN_free(*bnp) + *bnp = nil + } + if b == nil { + return true + } + bn := bigToBN(b) + if bn == nil { + return false + } + *bnp = bn + return true +} + +// noescape hides a pointer from escape analysis. noescape is +// the identity function but escape analysis doesn't think the +// output depends on the input. noescape is inlined and currently +// compiles down to zero instructions. +// USE CAREFULLY! +// +//go:nosplit +func noescape(p unsafe.Pointer) unsafe.Pointer { + x := uintptr(p) + return unsafe.Pointer(x ^ 0) +} + +var zero byte + +// addr converts p to its base addr, including a noescape along the way. +// If p is nil, addr returns a non-nil pointer, so that the result can always +// be dereferenced. +// +//go:nosplit +func addr(p []byte) *byte { + if len(p) == 0 { + return &zero + } + return (*byte)(noescape(unsafe.Pointer(&p[0]))) +} diff --git a/crypto/internal/boring/boring_test.go b/crypto/internal/boring/boring_test.go new file mode 100644 index 00000000000..83bbbd34049 --- /dev/null +++ b/crypto/internal/boring/boring_test.go @@ -0,0 +1,34 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Most functionality in this package is tested by replacing existing code +// and inheriting that code's tests. + +package boring + +import "testing" + +// Test that func init does not panic. +func TestInit(t *testing.T) {} + +// Test that Unreachable panics. +func TestUnreachable(t *testing.T) { + defer func() { + if Enabled { + if err := recover(); err == nil { + t.Fatal("expected Unreachable to panic") + } + } else { + if err := recover(); err != nil { + t.Fatalf("expected Unreachable to be a no-op") + } + } + }() + Unreachable() +} + +// Test that UnreachableExceptTests does not panic (this is a test). +func TestUnreachableExceptTests(t *testing.T) { + UnreachableExceptTests() +} diff --git a/crypto/internal/boring/build-boring.sh b/crypto/internal/boring/build-boring.sh new file mode 100755 index 00000000000..c7dc4f37ad5 --- /dev/null +++ b/crypto/internal/boring/build-boring.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Copyright 2020 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Do not run directly; run build.sh, which runs this in Docker. +# This script builds boringssl, which has already been unpacked in /boring/boringssl. + +set -e +id +date +cd /boring + +# Go requires -fPIC for linux/amd64 cgo builds. +# Setting -fPIC only affects the compilation of the non-module code in libcrypto.a, +# because the FIPS module itself is already built with -fPIC. +echo '#!/bin/bash +exec clang-'$ClangV' -DGOBORING -fPIC "$@" +' >/usr/local/bin/clang +echo '#!/bin/bash +exec clang++-'$ClangV' -DGOBORING -fPIC "$@" +' >/usr/local/bin/clang++ +chmod +x /usr/local/bin/clang /usr/local/bin/clang++ + +# The BoringSSL tests use Go, and cgo would look for gcc. +export CGO_ENABLED=0 + +# Modify the support code crypto/mem.c (outside the FIPS module) +# to not try to use weak symbols, because they don't work with some +# Go toolchain / clang toolchain combinations. +perl -p -i -e 's/defined.*ELF.*defined.*GNUC.*/$0 \&\& !defined(GOBORING)/' boringssl/crypto/mem.c + +# We build all of libcrypto, which includes a bunch of I/O operations that we +# don't actually care about, since we only really want the BoringCrypto module. +# In libcrypto, they use the LFS64 interfaces where available in order to +# traverse files larger than 2GB. In some scenarios this can cause breakage, so +# we comment out the _FILE_OFFSET_BITS definition which enables the LFS64 +# interfaces. Since this code is outside of the FIPS module, it doesn't affect +# the certification status of the module. See b/364606941 for additional context. +perl -p -i -e 's/(#define _FILE_OFFSET_BITS 64)/\/\/ $1/' boringssl/crypto/bio/file.c + +# Verbatim instructions from BoringCrypto build docs. +printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" >${HOME}/toolchain +cd boringssl +mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=${HOME}/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release .. +# SSLTest.HostMatching fails due to an expired certificate. +ninja && faketime 2022-06-13 ninja run_tests +cd ../.. + +if [ "$(./boringssl/build/tool/bssl isfips)" != 1 ]; then + echo "NOT FIPS" + exit 2 +fi diff --git a/crypto/internal/boring/build-goboring.sh b/crypto/internal/boring/build-goboring.sh new file mode 100755 index 00000000000..c43fad24e8b --- /dev/null +++ b/crypto/internal/boring/build-goboring.sh @@ -0,0 +1,237 @@ +#!/bin/bash +# Copyright 2020 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Do not run directly; run build.sh, which runs this in Docker. +# This script builds goboringcrypto's syso, after boringssl has been built. + +export TERM=dumb + +set -e +set -x +id +date +export LANG=C +unset LANGUAGE + +case $(uname -m) in +x86_64) export GOARCH=amd64 ;; +aarch64) export GOARCH=arm64 ;; +*) + echo 'unknown uname -m:' $(uname -m) >&2 + exit 2 +esac + +export CGO_ENABLED=0 + +# Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h. +# Also collect list of checked symbols in syms.txt +set -e +cd /boring/godriver +cat >goboringcrypto.cc <<'EOF' +#include +#include "goboringcrypto0.h" +#include "goboringcrypto1.h" +#define check_size(t) if(sizeof(t) != sizeof(GO_ ## t)) {printf("sizeof(" #t ")=%d, but sizeof(GO_" #t ")=%d\n", (int)sizeof(t), (int)sizeof(GO_ ## t)); ret=1;} +#define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; } +#define check_value(n, v) if(n != v) {printf(#n "=%d, but goboringcrypto.h defines it as %d\n", (int)n, (int)v); ret=1;} +int main() { +int ret = 0; +#include "goboringcrypto.x" +return ret; +} +EOF + +cat >boringx.awk <<'EOF' +BEGIN { + exitcode = 0 +} + +# Ignore comments, #includes, blank lines. +/^\/\// || /^#/ || NF == 0 { next } + +# Ignore unchecked declarations. +/\/\*unchecked/ { next } + +# Check enum values. +!enum && ($1 == "enum" || $2 == "enum") && $NF == "{" { + enum = 1 + next +} +enum && $1 == "};" { + enum = 0 + next +} +enum && /^}.*;$/ { + enum = 0 + next +} +enum && NF == 3 && $2 == "=" { + name = $1 + sub(/^GO_/, "", name) + val = $3 + sub(/,$/, "", val) + print "check_value(" name ", " val ")" > "goboringcrypto.x" + next +} +enum { + print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr" + exitcode = 1 + next +} + +# Check struct sizes. +/^typedef struct / && $NF ~ /^GO_/ { + name = $NF + sub(/^GO_/, "", name) + sub(/;$/, "", name) + print "check_size(" name ")" > "goboringcrypto.x" + next +} + +# Check function prototypes. +/^(const )?[^ ]+ \**_goboringcrypto_.*\(/ { + name = $2 + if($1 == "const") + name = $3 + sub(/^\**_goboringcrypto_/, "", name) + sub(/\(.*/, "", name) + print "check_func(" name ")" > "goboringcrypto.x" + print name > "syms.txt" + next +} + +{ + print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr" + exitcode = 1 +} + +END { + exit exitcode +} +EOF + +cat >boringh.awk <<'EOF' +/^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next} +/typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print >"goboringcrypto1.h";next} +{gsub(/GO_/, ""); gsub(/enum go_/, "enum "); gsub(/go_point_conv/, "point_conv"); print >"goboringcrypto1.h"} +EOF + +awk -f boringx.awk goboringcrypto.h # writes goboringcrypto.x +awk -f boringh.awk goboringcrypto.h # writes goboringcrypto[01].h + +ls -l ../boringssl/include +clang++ -fPIC -I../boringssl/include -O2 -o a.out goboringcrypto.cc +./a.out || exit 2 + +# clang implements u128 % u128 -> u128 by calling __umodti3, +# which is in libgcc. To make the result self-contained even if linking +# against a different compiler version, link our own __umodti3 into the syso. +# This one is specialized so it only expects divisors below 2^64, +# which is all BoringCrypto uses. (Otherwise it will seg fault.) +cat >umod-amd64.s <<'EOF' +# tu_int __umodti3(tu_int x, tu_int y) +# x is rsi:rdi, y is rcx:rdx, return result is rdx:rax. +.globl __umodti3 +__umodti3: + # specialized to u128 % u64, so verify that + test %rcx,%rcx + jne 1f + + # save divisor + movq %rdx, %r8 + + # reduce top 64 bits mod divisor + movq %rsi, %rax + xorl %edx, %edx + divq %r8 + + # reduce full 128-bit mod divisor + # quotient fits in 64 bits because top 64 bits have been reduced < divisor. + # (even though we only care about the remainder, divq also computes + # the quotient, and it will trap if the quotient is too large.) + movq %rdi, %rax + divq %r8 + + # expand remainder to 128 for return + movq %rdx, %rax + xorl %edx, %edx + ret + +1: + # crash - only want 64-bit divisor + xorl %ecx, %ecx + movl %ecx, 0(%ecx) + jmp 1b + +.section .note.GNU-stack,"",@progbits +EOF + +cat >umod-arm64.c <<'EOF' +typedef unsigned int u128 __attribute__((mode(TI))); + +static u128 div(u128 x, u128 y, u128 *rp) { + int n = 0; + while((y>>(128-1)) != 1 && y < x) { + y<<=1; + n++; + } + u128 q = 0; + for(;; n--, y>>=1, q<<=1) { + if(x>=y) { + x -= y; + q |= 1; + } + if(n == 0) + break; + } + if(rp) + *rp = x; + return q; +} + +u128 __umodti3(u128 x, u128 y) { + u128 r; + div(x, y, &r); + return r; +} + +u128 __udivti3(u128 x, u128 y) { + return div(x, y, 0); +} +EOF + +extra="" +case $GOARCH in +amd64) + cp umod-amd64.s umod.s + clang -c -o umod.o umod.s + extra=umod.o + ;; +arm64) + cp umod-arm64.c umod.c + clang -c -o umod.o umod.c + extra=umod.o + ;; +esac + +# Prepare copy of libcrypto.a with only the checked functions renamed and exported. +# All other symbols are left alone and hidden. +echo BORINGSSL_bcm_power_on_self_test >>syms.txt +awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt +awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt +objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test \ + ../boringssl/build/crypto/libcrypto.a libcrypto.a + +# Link together bcm.o and libcrypto.a into a single object. +ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a $extra + +echo __umodti3 _goboringcrypto___umodti3 >>renames.txt +echo __udivti3 _goboringcrypto___udivti3 >>renames.txt +objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016 +objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o +objcopy --keep-global-symbols=globals.txt --strip-unneeded goboringcrypto2.o goboringcrypto_linux_$GOARCH.syso + +# Done! +ls -l goboringcrypto_linux_$GOARCH.syso diff --git a/crypto/internal/boring/build.sh b/crypto/internal/boring/build.sh new file mode 100755 index 00000000000..e2026018a39 --- /dev/null +++ b/crypto/internal/boring/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This shell script uses Docker to run build-boring.sh and build-goboring.sh, +# which build goboringcrypto_linux_$GOARCH.syso according to the Security Policy. +# Currently, amd64 and arm64 are permitted. + +set -e +set -o pipefail + +GOARCH=${GOARCH:-$(go env GOARCH)} +echo "# Building goboringcrypto_linux_$GOARCH.syso. Set GOARCH to override." >&2 + +if ! which docker >/dev/null; then + echo "# Docker not found. Inside Google, see go/installdocker." >&2 + exit 1 +fi + +platform="" +buildargs="" +case "$GOARCH" in +amd64) + if ! docker run --rm -t amd64/ubuntu:focal uname -m >/dev/null 2>&1; then + echo "# Docker cannot run amd64 binaries." + exit 1 + fi + platform="--platform linux/amd64" + buildargs="--build-arg ubuntu=amd64/ubuntu" + ;; +arm64) + if ! docker run --rm -t arm64v8/ubuntu:focal uname -m >/dev/null 2>&1; then + echo "# Docker cannot run arm64 binaries. Try:" + echo " sudo apt-get install qemu binfmt-support qemu-user-static" + echo " docker run --rm --privileged multiarch/qemu-user-static --reset -p yes" + echo " docker run --rm -t arm64v8/ubuntu:focal uname -m" + exit 1 + fi + platform="--platform linux/arm64/v8" + buildargs="--build-arg ubuntu=arm64v8/ubuntu" + ;; +*) + echo unknown GOARCH $GOARCH >&2 + exit 2 +esac + +docker build $platform $buildargs --build-arg GOARCH=$GOARCH -t goboring:$GOARCH . +id=$(docker create $platform goboring:$GOARCH) +docker cp $id:/boring/godriver/goboringcrypto_linux_$GOARCH.syso ./syso +docker rm $id +ls -l ./syso/goboringcrypto_linux_$GOARCH.syso diff --git a/crypto/internal/boring/div_test.c b/crypto/internal/boring/div_test.c new file mode 100644 index 00000000000..f909cc93f43 --- /dev/null +++ b/crypto/internal/boring/div_test.c @@ -0,0 +1,83 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is a self-contained test for a copy of +// the division algorithm in build-goboring.sh, +// to verify that is correct. The real algorithm uses u128 +// but this copy uses u32 for easier testing. +// s/32/128/g should be the only difference between the two. +// +// This is the dumbest possible division algorithm, +// but any crypto code that depends on the speed of +// division is equally dumb. + +//go:build ignore + +#include +#include + +#define nelem(x) (sizeof(x)/sizeof((x)[0])) + +typedef uint32_t u32; + +static u32 div(u32 x, u32 y, u32 *rp) { + int n = 0; + while((y>>(32-1)) != 1 && y < x) { + y<<=1; + n++; + } + u32 q = 0; + for(;; n--, y>>=1, q<<=1) { + if(x>=y) { + x -= y; + q |= 1; + } + if(n == 0) + break; + } + if(rp) + *rp = x; + return q; +} + +u32 tests[] = { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 31, + 0xFFF, + 0x1000, + 0x1001, + 0xF0F0F0, + 0xFFFFFF, + 0x1000000, + 0xF0F0F0F0, + 0xFFFFFFFF, +}; + +int +main(void) +{ + for(int i=0; i // size_t +#include // uint8_t + +// This symbol is hidden in BoringCrypto and marked as a constructor, +// but cmd/link's internal linking mode doesn't handle constructors. +// Until it does, we've exported the symbol and can call it explicitly. +// (If using external linking mode, it will therefore be called twice, +// once explicitly and once as a constructor, but that's OK.) +/*unchecked*/ void _goboringcrypto_BORINGSSL_bcm_power_on_self_test(void); + +// #include +int _goboringcrypto_FIPS_mode(void); +void* _goboringcrypto_OPENSSL_malloc(size_t); + +// #include +int _goboringcrypto_RAND_bytes(uint8_t*, size_t); + +// #include +enum { + GO_NID_md5_sha1 = 114, + + GO_NID_secp224r1 = 713, + GO_NID_X9_62_prime256v1 = 415, + GO_NID_secp384r1 = 715, + GO_NID_secp521r1 = 716, + + GO_NID_sha224 = 675, + GO_NID_sha256 = 672, + GO_NID_sha384 = 673, + GO_NID_sha512 = 674, +}; + +// #include +typedef struct GO_SHA_CTX { char data[96]; } GO_SHA_CTX; +int _goboringcrypto_SHA1_Init(GO_SHA_CTX*); +int _goboringcrypto_SHA1_Update(GO_SHA_CTX*, const void*, size_t); +int _goboringcrypto_SHA1_Final(uint8_t*, GO_SHA_CTX*); + +typedef struct GO_SHA256_CTX { char data[48+64]; } GO_SHA256_CTX; +int _goboringcrypto_SHA224_Init(GO_SHA256_CTX*); +int _goboringcrypto_SHA224_Update(GO_SHA256_CTX*, const void*, size_t); +int _goboringcrypto_SHA224_Final(uint8_t*, GO_SHA256_CTX*); +int _goboringcrypto_SHA256_Init(GO_SHA256_CTX*); +int _goboringcrypto_SHA256_Update(GO_SHA256_CTX*, const void*, size_t); +int _goboringcrypto_SHA256_Final(uint8_t*, GO_SHA256_CTX*); + +typedef struct GO_SHA512_CTX { char data[88+128]; } GO_SHA512_CTX; +int _goboringcrypto_SHA384_Init(GO_SHA512_CTX*); +int _goboringcrypto_SHA384_Update(GO_SHA512_CTX*, const void*, size_t); +int _goboringcrypto_SHA384_Final(uint8_t*, GO_SHA512_CTX*); +int _goboringcrypto_SHA512_Init(GO_SHA512_CTX*); +int _goboringcrypto_SHA512_Update(GO_SHA512_CTX*, const void*, size_t); +int _goboringcrypto_SHA512_Final(uint8_t*, GO_SHA512_CTX*); + +// #include +/*unchecked (opaque)*/ typedef struct GO_EVP_MD { char data[1]; } GO_EVP_MD; +const GO_EVP_MD* _goboringcrypto_EVP_md4(void); +const GO_EVP_MD* _goboringcrypto_EVP_md5(void); +const GO_EVP_MD* _goboringcrypto_EVP_md5_sha1(void); +const GO_EVP_MD* _goboringcrypto_EVP_sha1(void); +const GO_EVP_MD* _goboringcrypto_EVP_sha224(void); +const GO_EVP_MD* _goboringcrypto_EVP_sha256(void); +const GO_EVP_MD* _goboringcrypto_EVP_sha384(void); +const GO_EVP_MD* _goboringcrypto_EVP_sha512(void); +int _goboringcrypto_EVP_MD_type(const GO_EVP_MD*); +size_t _goboringcrypto_EVP_MD_size(const GO_EVP_MD*); + +// #include +typedef struct GO_HMAC_CTX { char data[104]; } GO_HMAC_CTX; +void _goboringcrypto_HMAC_CTX_init(GO_HMAC_CTX*); +void _goboringcrypto_HMAC_CTX_cleanup(GO_HMAC_CTX*); +int _goboringcrypto_HMAC_Init(GO_HMAC_CTX*, const void*, int, const GO_EVP_MD*); +int _goboringcrypto_HMAC_Update(GO_HMAC_CTX*, const uint8_t*, size_t); +int _goboringcrypto_HMAC_Final(GO_HMAC_CTX*, uint8_t*, unsigned int*); +size_t _goboringcrypto_HMAC_size(const GO_HMAC_CTX*); +int _goboringcrypto_HMAC_CTX_copy_ex(GO_HMAC_CTX *dest, const GO_HMAC_CTX *src); + +// #include +typedef struct GO_AES_KEY { char data[244]; } GO_AES_KEY; +int _goboringcrypto_AES_set_encrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*); +int _goboringcrypto_AES_set_decrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*); +void _goboringcrypto_AES_encrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*); +void _goboringcrypto_AES_decrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*); +void _goboringcrypto_AES_ctr128_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, uint8_t*, unsigned int*); +enum { + GO_AES_ENCRYPT = 1, + GO_AES_DECRYPT = 0 +}; +void _goboringcrypto_AES_cbc_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, const int); + +// #include +/*unchecked (opaque)*/ typedef struct GO_EVP_AEAD { char data[1]; } GO_EVP_AEAD; +/*unchecked (opaque)*/ typedef struct GO_ENGINE { char data[1]; } GO_ENGINE; +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm(void); +enum { + GO_EVP_AEAD_DEFAULT_TAG_LENGTH = 0 +}; +size_t _goboringcrypto_EVP_AEAD_key_length(const GO_EVP_AEAD*); +size_t _goboringcrypto_EVP_AEAD_nonce_length(const GO_EVP_AEAD*); +size_t _goboringcrypto_EVP_AEAD_max_overhead(const GO_EVP_AEAD*); +size_t _goboringcrypto_EVP_AEAD_max_tag_len(const GO_EVP_AEAD*); +typedef struct GO_EVP_AEAD_CTX { char data[600]; } GO_EVP_AEAD_CTX; +void _goboringcrypto_EVP_AEAD_CTX_zero(GO_EVP_AEAD_CTX*); +int _goboringcrypto_EVP_AEAD_CTX_init(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, GO_ENGINE*); +void _goboringcrypto_EVP_AEAD_CTX_cleanup(GO_EVP_AEAD_CTX*); +int _goboringcrypto_EVP_AEAD_CTX_seal(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t); +int _goboringcrypto_EVP_AEAD_CTX_open(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls12(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls13(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls12(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls13(void); +enum go_evp_aead_direction_t { + go_evp_aead_open = 0, + go_evp_aead_seal = 1 +}; +int _goboringcrypto_EVP_AEAD_CTX_init_with_direction(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, enum go_evp_aead_direction_t); + +// #include +/*unchecked (opaque)*/ typedef struct GO_BN_CTX { char data[1]; } GO_BN_CTX; +typedef struct GO_BIGNUM { char data[24]; } GO_BIGNUM; +GO_BIGNUM* _goboringcrypto_BN_new(void); +void _goboringcrypto_BN_free(GO_BIGNUM*); +unsigned _goboringcrypto_BN_num_bits(const GO_BIGNUM*); +unsigned _goboringcrypto_BN_num_bytes(const GO_BIGNUM*); +int _goboringcrypto_BN_is_negative(const GO_BIGNUM*); +GO_BIGNUM* _goboringcrypto_BN_bin2bn(const uint8_t*, size_t, GO_BIGNUM*); +GO_BIGNUM* _goboringcrypto_BN_le2bn(const uint8_t*, size_t, GO_BIGNUM*); +size_t _goboringcrypto_BN_bn2bin(const GO_BIGNUM*, uint8_t*); +int _goboringcrypto_BN_bn2le_padded(uint8_t*, size_t, const GO_BIGNUM*); +int _goboringcrypto_BN_bn2bin_padded(uint8_t*, size_t, const GO_BIGNUM*); + +// #include +/*unchecked (opaque)*/ typedef struct GO_EC_GROUP { char data[1]; } GO_EC_GROUP; +GO_EC_GROUP* _goboringcrypto_EC_GROUP_new_by_curve_name(int); +void _goboringcrypto_EC_GROUP_free(GO_EC_GROUP*); + +/*unchecked (opaque)*/ typedef struct GO_EC_POINT { char data[1]; } GO_EC_POINT; +GO_EC_POINT* _goboringcrypto_EC_POINT_new(const GO_EC_GROUP*); +int _goboringcrypto_EC_POINT_mul(const GO_EC_GROUP*, GO_EC_POINT*, const GO_BIGNUM*, const GO_EC_POINT*, const GO_BIGNUM*, GO_BN_CTX*); +void _goboringcrypto_EC_POINT_free(GO_EC_POINT*); +int _goboringcrypto_EC_POINT_get_affine_coordinates_GFp(const GO_EC_GROUP*, const GO_EC_POINT*, GO_BIGNUM*, GO_BIGNUM*, GO_BN_CTX*); +int _goboringcrypto_EC_POINT_set_affine_coordinates_GFp(const GO_EC_GROUP*, GO_EC_POINT*, const GO_BIGNUM*, const GO_BIGNUM*, GO_BN_CTX*); +int _goboringcrypto_EC_POINT_oct2point(const GO_EC_GROUP*, GO_EC_POINT*, const uint8_t*, size_t, GO_BN_CTX*); +GO_EC_POINT* _goboringcrypto_EC_POINT_dup(const GO_EC_POINT*, const GO_EC_GROUP*); +int _goboringcrypto_EC_POINT_is_on_curve(const GO_EC_GROUP*, const GO_EC_POINT*, GO_BN_CTX*); +#ifndef OPENSSL_HEADER_EC_H +typedef enum { + GO_POINT_CONVERSION_COMPRESSED = 2, + GO_POINT_CONVERSION_UNCOMPRESSED = 4, + GO_POINT_CONVERSION_HYBRID = 6, +} go_point_conversion_form_t; +#endif +size_t _goboringcrypto_EC_POINT_point2oct(const GO_EC_GROUP*, const GO_EC_POINT*, go_point_conversion_form_t, uint8_t*, size_t, GO_BN_CTX*); + +// #include +/*unchecked (opaque)*/ typedef struct GO_EC_KEY { char data[1]; } GO_EC_KEY; +GO_EC_KEY* _goboringcrypto_EC_KEY_new(void); +GO_EC_KEY* _goboringcrypto_EC_KEY_new_by_curve_name(int); +void _goboringcrypto_EC_KEY_free(GO_EC_KEY*); +const GO_EC_GROUP* _goboringcrypto_EC_KEY_get0_group(const GO_EC_KEY*); +int _goboringcrypto_EC_KEY_generate_key_fips(GO_EC_KEY*); +int _goboringcrypto_EC_KEY_set_private_key(GO_EC_KEY*, const GO_BIGNUM*); +int _goboringcrypto_EC_KEY_set_public_key(GO_EC_KEY*, const GO_EC_POINT*); +int _goboringcrypto_EC_KEY_is_opaque(const GO_EC_KEY*); +const GO_BIGNUM* _goboringcrypto_EC_KEY_get0_private_key(const GO_EC_KEY*); +const GO_EC_POINT* _goboringcrypto_EC_KEY_get0_public_key(const GO_EC_KEY*); +// TODO: EC_KEY_check_fips? + +// #include +int _goboringcrypto_ECDH_compute_key_fips(uint8_t*, size_t, const GO_EC_POINT*, const GO_EC_KEY*); + +// #include +typedef struct GO_ECDSA_SIG { char data[16]; } GO_ECDSA_SIG; +GO_ECDSA_SIG* _goboringcrypto_ECDSA_SIG_new(void); +void _goboringcrypto_ECDSA_SIG_free(GO_ECDSA_SIG*); +GO_ECDSA_SIG* _goboringcrypto_ECDSA_do_sign(const uint8_t*, size_t, const GO_EC_KEY*); +int _goboringcrypto_ECDSA_do_verify(const uint8_t*, size_t, const GO_ECDSA_SIG*, const GO_EC_KEY*); +int _goboringcrypto_ECDSA_sign(int, const uint8_t*, size_t, uint8_t*, unsigned int*, const GO_EC_KEY*); +size_t _goboringcrypto_ECDSA_size(const GO_EC_KEY*); +int _goboringcrypto_ECDSA_verify(int, const uint8_t*, size_t, const uint8_t*, size_t, const GO_EC_KEY*); + +// #include + +// Note: order of struct fields here is unchecked. +typedef struct GO_RSA { void *meth; GO_BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; char data[168]; } GO_RSA; +/*unchecked (opaque)*/ typedef struct GO_BN_GENCB { char data[1]; } GO_BN_GENCB; +GO_RSA* _goboringcrypto_RSA_new(void); +void _goboringcrypto_RSA_free(GO_RSA*); +void _goboringcrypto_RSA_get0_key(const GO_RSA*, const GO_BIGNUM **n, const GO_BIGNUM **e, const GO_BIGNUM **d); +void _goboringcrypto_RSA_get0_factors(const GO_RSA*, const GO_BIGNUM **p, const GO_BIGNUM **q); +void _goboringcrypto_RSA_get0_crt_params(const GO_RSA*, const GO_BIGNUM **dmp1, const GO_BIGNUM **dmp2, const GO_BIGNUM **iqmp); +int _goboringcrypto_RSA_generate_key_ex(GO_RSA*, int, const GO_BIGNUM*, GO_BN_GENCB*); +int _goboringcrypto_RSA_generate_key_fips(GO_RSA*, int, GO_BN_GENCB*); +enum { + GO_RSA_PKCS1_PADDING = 1, + GO_RSA_NO_PADDING = 3, + GO_RSA_PKCS1_OAEP_PADDING = 4, + GO_RSA_PKCS1_PSS_PADDING = 6, +}; +int _goboringcrypto_RSA_encrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); +int _goboringcrypto_RSA_decrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); +int _goboringcrypto_RSA_sign(int hash_nid, const uint8_t* in, unsigned int in_len, uint8_t *out, unsigned int *out_len, GO_RSA*); +int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len); +int _goboringcrypto_RSA_sign_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); +int _goboringcrypto_RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, GO_RSA*); +int _goboringcrypto_RSA_verify_pss_mgf1(GO_RSA*, const uint8_t *msg, size_t msg_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len, const uint8_t *sig, size_t sig_len); +int _goboringcrypto_RSA_verify_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); +unsigned _goboringcrypto_RSA_size(const GO_RSA*); +int _goboringcrypto_RSA_is_opaque(const GO_RSA*); +int _goboringcrypto_RSA_check_key(const GO_RSA*); +int _goboringcrypto_RSA_check_fips(GO_RSA*); +GO_RSA* _goboringcrypto_RSA_public_key_from_bytes(const uint8_t*, size_t); +GO_RSA* _goboringcrypto_RSA_private_key_from_bytes(const uint8_t*, size_t); +int _goboringcrypto_RSA_public_key_to_bytes(uint8_t**, size_t*, const GO_RSA*); +int _goboringcrypto_RSA_private_key_to_bytes(uint8_t**, size_t*, const GO_RSA*); + +// #include +/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY { char data[1]; } GO_EVP_PKEY; +GO_EVP_PKEY* _goboringcrypto_EVP_PKEY_new(void); +void _goboringcrypto_EVP_PKEY_free(GO_EVP_PKEY*); +int _goboringcrypto_EVP_PKEY_set1_RSA(GO_EVP_PKEY*, GO_RSA*); + +/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY_CTX { char data[1]; } GO_EVP_PKEY_CTX; + +GO_EVP_PKEY_CTX* _goboringcrypto_EVP_PKEY_CTX_new(GO_EVP_PKEY*, GO_ENGINE*); +void _goboringcrypto_EVP_PKEY_CTX_free(GO_EVP_PKEY_CTX*); +int _goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(GO_EVP_PKEY_CTX*, uint8_t*, size_t); +int _goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*); +int _goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(GO_EVP_PKEY_CTX*, int padding); +int _goboringcrypto_EVP_PKEY_decrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t); +int _goboringcrypto_EVP_PKEY_encrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t); +int _goboringcrypto_EVP_PKEY_decrypt_init(GO_EVP_PKEY_CTX*); +int _goboringcrypto_EVP_PKEY_encrypt_init(GO_EVP_PKEY_CTX*); +int _goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*); +int _goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(GO_EVP_PKEY_CTX*, int); +int _goboringcrypto_EVP_PKEY_sign_init(GO_EVP_PKEY_CTX*); +int _goboringcrypto_EVP_PKEY_verify_init(GO_EVP_PKEY_CTX*); +int _goboringcrypto_EVP_PKEY_sign(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t); diff --git a/crypto/internal/boring/hmac.go b/crypto/internal/boring/hmac.go new file mode 100644 index 00000000000..e90c5743e25 --- /dev/null +++ b/crypto/internal/boring/hmac.go @@ -0,0 +1,155 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +// #include "goboringcrypto.h" +import "C" +import ( + "bytes" + "runtime" + "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto" +) + +// hashToMD converts a hash.Hash implementation from this package +// to a BoringCrypto *C.GO_EVP_MD. +func hashToMD(h hash.Hash) *C.GO_EVP_MD { + switch h.(type) { + case *sha1Hash: + return C._goboringcrypto_EVP_sha1() + case *sha224Hash: + return C._goboringcrypto_EVP_sha224() + case *sha256Hash: + return C._goboringcrypto_EVP_sha256() + case *sha384Hash: + return C._goboringcrypto_EVP_sha384() + case *sha512Hash: + return C._goboringcrypto_EVP_sha512() + } + return nil +} + +// cryptoHashToMD converts a crypto.Hash +// to a BoringCrypto *C.GO_EVP_MD. +func cryptoHashToMD(ch crypto.Hash) *C.GO_EVP_MD { + switch ch { + case crypto.MD5: + return C._goboringcrypto_EVP_md5() + case crypto.MD5SHA1: + return C._goboringcrypto_EVP_md5_sha1() + case crypto.SHA1: + return C._goboringcrypto_EVP_sha1() + case crypto.SHA224: + return C._goboringcrypto_EVP_sha224() + case crypto.SHA256: + return C._goboringcrypto_EVP_sha256() + case crypto.SHA384: + return C._goboringcrypto_EVP_sha384() + case crypto.SHA512: + return C._goboringcrypto_EVP_sha512() + } + return nil +} + +// NewHMAC returns a new HMAC using BoringCrypto. +// The function h must return a hash implemented by +// BoringCrypto (for example, h could be boring.NewSHA256). +// If h is not recognized, NewHMAC returns nil. +func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { + ch := h() + md := hashToMD(ch) + if md == nil { + return nil + } + + // Note: Could hash down long keys here using EVP_Digest. + hkey := bytes.Clone(key) + hmac := &boringHMAC{ + md: md, + size: ch.Size(), + blockSize: ch.BlockSize(), + key: hkey, + } + hmac.Reset() + return hmac +} + +type boringHMAC struct { + md *C.GO_EVP_MD + ctx C.GO_HMAC_CTX + ctx2 C.GO_HMAC_CTX + size int + blockSize int + key []byte + sum []byte + needCleanup bool +} + +func (h *boringHMAC) Reset() { + if h.needCleanup { + C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx) + } else { + h.needCleanup = true + // Note: Because of the finalizer, any time h.ctx is passed to cgo, + // that call must be followed by a call to runtime.KeepAlive(h), + // to make sure h is not collected (and finalized) before the cgo + // call returns. + runtime.SetFinalizer(h, (*boringHMAC).finalize) + } + C._goboringcrypto_HMAC_CTX_init(&h.ctx) + + if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md) == 0 { + panic("boringcrypto: HMAC_Init failed") + } + if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size { + println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size) + panic("boringcrypto: HMAC size mismatch") + } + runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure. + h.sum = nil +} + +func (h *boringHMAC) finalize() { + C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx) +} + +func (h *boringHMAC) Write(p []byte) (int, error) { + if len(p) > 0 { + C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p))) + } + runtime.KeepAlive(h) + return len(p), nil +} + +func (h *boringHMAC) Size() int { + return h.size +} + +func (h *boringHMAC) BlockSize() int { + return h.blockSize +} + +func (h *boringHMAC) Sum(in []byte) []byte { + if h.sum == nil { + size := h.Size() + h.sum = make([]byte, size) + } + // Make copy of context because Go hash.Hash mandates + // that Sum has no effect on the underlying stream. + // In particular it is OK to Sum, then Write more, then Sum again, + // and the second Sum acts as if the first didn't happen. + C._goboringcrypto_HMAC_CTX_init(&h.ctx2) + if C._goboringcrypto_HMAC_CTX_copy_ex(&h.ctx2, &h.ctx) == 0 { + panic("boringcrypto: HMAC_CTX_copy_ex failed") + } + C._goboringcrypto_HMAC_Final(&h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil) + C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx2) + return append(in, h.sum...) +} diff --git a/crypto/internal/boring/notboring.go b/crypto/internal/boring/notboring.go index 162fe19f071..163805ce2aa 100644 --- a/crypto/internal/boring/notboring.go +++ b/crypto/internal/boring/notboring.go @@ -2,13 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !(boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo) + package boring import ( + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/internal/boring/sig" - "hash" ) const available = false diff --git a/crypto/internal/boring/rand.go b/crypto/internal/boring/rand.go new file mode 100644 index 00000000000..556b98a1124 --- /dev/null +++ b/crypto/internal/boring/rand.go @@ -0,0 +1,24 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +// #include "goboringcrypto.h" +import "C" +import "unsafe" + +type randReader int + +func (randReader) Read(b []byte) (int, error) { + // Note: RAND_bytes should never fail; the return value exists only for historical reasons. + // We check it even so. + if len(b) > 0 && C._goboringcrypto_RAND_bytes((*C.uint8_t)(unsafe.Pointer(&b[0])), C.size_t(len(b))) == 0 { + return 0, fail("RAND_bytes") + } + return len(b), nil +} + +const RandReader = randReader(0) diff --git a/crypto/internal/boring/rsa.go b/crypto/internal/boring/rsa.go new file mode 100644 index 00000000000..5e0d336e2a2 --- /dev/null +++ b/crypto/internal/boring/rsa.go @@ -0,0 +1,381 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +// #include "goboringcrypto.h" +import "C" +import ( + "errors" + "runtime" + "strconv" + "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/subtle" +) + +func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { + bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { + return nil, nil, nil, nil, nil, nil, nil, nil, e + } + + key := C._goboringcrypto_RSA_new() + if key == nil { + return bad(fail("RSA_new")) + } + defer C._goboringcrypto_RSA_free(key) + + if C._goboringcrypto_RSA_generate_key_fips(key, C.int(bits), nil) == 0 { + return bad(fail("RSA_generate_key_fips")) + } + + var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM + C._goboringcrypto_RSA_get0_key(key, &n, &e, &d) + C._goboringcrypto_RSA_get0_factors(key, &p, &q) + C._goboringcrypto_RSA_get0_crt_params(key, &dp, &dq, &qinv) + return bnToBig(n), bnToBig(e), bnToBig(d), bnToBig(p), bnToBig(q), bnToBig(dp), bnToBig(dq), bnToBig(qinv), nil +} + +type PublicKeyRSA struct { + // _key MUST NOT be accessed directly. Instead, use the withKey method. + _key *C.GO_RSA +} + +func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) { + key := C._goboringcrypto_RSA_new() + if key == nil { + return nil, fail("RSA_new") + } + if !bigToBn(&key.n, N) || + !bigToBn(&key.e, E) { + return nil, fail("BN_bin2bn") + } + k := &PublicKeyRSA{_key: key} + runtime.SetFinalizer(k, (*PublicKeyRSA).finalize) + return k, nil +} + +func (k *PublicKeyRSA) finalize() { + C._goboringcrypto_RSA_free(k._key) +} + +func (k *PublicKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int { + // Because of the finalizer, any time _key is passed to cgo, that call must + // be followed by a call to runtime.KeepAlive, to make sure k is not + // collected (and finalized) before the cgo call returns. + defer runtime.KeepAlive(k) + return f(k._key) +} + +type PrivateKeyRSA struct { + // _key MUST NOT be accessed directly. Instead, use the withKey method. + _key *C.GO_RSA +} + +func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error) { + key := C._goboringcrypto_RSA_new() + if key == nil { + return nil, fail("RSA_new") + } + if !bigToBn(&key.n, N) || + !bigToBn(&key.e, E) || + !bigToBn(&key.d, D) || + !bigToBn(&key.p, P) || + !bigToBn(&key.q, Q) || + !bigToBn(&key.dmp1, Dp) || + !bigToBn(&key.dmq1, Dq) || + !bigToBn(&key.iqmp, Qinv) { + return nil, fail("BN_bin2bn") + } + k := &PrivateKeyRSA{_key: key} + runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize) + return k, nil +} + +func (k *PrivateKeyRSA) finalize() { + C._goboringcrypto_RSA_free(k._key) +} + +func (k *PrivateKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int { + // Because of the finalizer, any time _key is passed to cgo, that call must + // be followed by a call to runtime.KeepAlive, to make sure k is not + // collected (and finalized) before the cgo call returns. + defer runtime.KeepAlive(k) + return f(k._key) +} + +func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, + padding C.int, h, mgfHash hash.Hash, label []byte, saltLen int, ch crypto.Hash, + init func(*C.GO_EVP_PKEY_CTX) C.int) (pkey *C.GO_EVP_PKEY, ctx *C.GO_EVP_PKEY_CTX, err error) { + defer func() { + if err != nil { + if pkey != nil { + C._goboringcrypto_EVP_PKEY_free(pkey) + pkey = nil + } + if ctx != nil { + C._goboringcrypto_EVP_PKEY_CTX_free(ctx) + ctx = nil + } + } + }() + + pkey = C._goboringcrypto_EVP_PKEY_new() + if pkey == nil { + return pkey, ctx, fail("EVP_PKEY_new") + } + if withKey(func(key *C.GO_RSA) C.int { + return C._goboringcrypto_EVP_PKEY_set1_RSA(pkey, key) + }) == 0 { + return pkey, ctx, fail("EVP_PKEY_set1_RSA") + } + ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil) + if ctx == nil { + return pkey, ctx, fail("EVP_PKEY_CTX_new") + } + if init(ctx) == 0 { + return pkey, ctx, fail("EVP_PKEY_operation_init") + } + if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 { + return pkey, ctx, fail("EVP_PKEY_CTX_set_rsa_padding") + } + if padding == C.GO_RSA_PKCS1_OAEP_PADDING { + md := hashToMD(h) + if md == nil { + return pkey, ctx, errors.New("crypto/rsa: unsupported hash function") + } + mgfMD := hashToMD(mgfHash) + if mgfMD == nil { + return pkey, ctx, errors.New("crypto/rsa: unsupported hash function") + } + if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 { + return pkey, ctx, fail("EVP_PKEY_set_rsa_oaep_md") + } + if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgfMD) == 0 { + return pkey, ctx, fail("EVP_PKEY_set_rsa_mgf1_md") + } + // ctx takes ownership of label, so malloc a copy for BoringCrypto to free. + clabel := (*C.uint8_t)(C._goboringcrypto_OPENSSL_malloc(C.size_t(len(label)))) + if clabel == nil { + return pkey, ctx, fail("OPENSSL_malloc") + } + copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) + if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 { + return pkey, ctx, fail("EVP_PKEY_CTX_set0_rsa_oaep_label") + } + } + if padding == C.GO_RSA_PKCS1_PSS_PADDING { + if saltLen != 0 { + if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 { + return pkey, ctx, fail("EVP_PKEY_set_rsa_pss_saltlen") + } + } + md := cryptoHashToMD(ch) + if md == nil { + return pkey, ctx, errors.New("crypto/rsa: unsupported hash function") + } + if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 { + return pkey, ctx, fail("EVP_PKEY_set_rsa_mgf1_md") + } + } + + return pkey, ctx, nil +} + +func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, + padding C.int, h, mgfHash hash.Hash, label []byte, saltLen int, ch crypto.Hash, + init func(*C.GO_EVP_PKEY_CTX) C.int, + crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int, + in []byte) ([]byte, error) { + + pkey, ctx, err := setupRSA(withKey, padding, h, mgfHash, label, saltLen, ch, init) + if err != nil { + return nil, err + } + defer C._goboringcrypto_EVP_PKEY_free(pkey) + defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx) + + var outLen C.size_t + if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 { + return nil, fail("EVP_PKEY_decrypt/encrypt") + } + out := make([]byte, outLen) + if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 { + return nil, fail("EVP_PKEY_decrypt/encrypt") + } + return out[:outLen], nil +} + +func DecryptRSAOAEP(h, mgfHash hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { + return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, decryptInit, decrypt, ciphertext) +} + +func EncryptRSAOAEP(h, mgfHash hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { + return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, encryptInit, encrypt, msg) +} + +func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { + return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) +} + +func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) { + return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg) +} + +func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { + return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) +} + +func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) { + return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg) +} + +// These dumb wrappers work around the fact that cgo functions cannot be used as values directly. + +func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { + return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx) +} + +func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { + return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen) +} + +func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { + return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx) +} + +func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { + return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen) +} + +var invalidSaltLenErr = errors.New("crypto/rsa: invalid PSS salt length") + +func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) { + md := cryptoHashToMD(h) + if md == nil { + return nil, errors.New("crypto/rsa: unsupported hash function") + } + + // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject + // it, and lengths < -2, before we convert to the BoringSSL sentinel values. + if saltLen <= -2 { + return nil, invalidSaltLenErr + } + + // BoringSSL uses sentinel salt length values like we do, but the values don't + // fully match what we use. We both use -1 for salt length equal to hash length, + // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter + // case convert to the BoringSSL version. + if saltLen == 0 { + saltLen = -2 + } + + var out []byte + var outLen C.size_t + if priv.withKey(func(key *C.GO_RSA) C.int { + out = make([]byte, C._goboringcrypto_RSA_size(key)) + return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.size_t(len(out)), + base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen)) + }) == 0 { + return nil, fail("RSA_sign_pss_mgf1") + } + + return out[:outLen], nil +} + +func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error { + md := cryptoHashToMD(h) + if md == nil { + return errors.New("crypto/rsa: unsupported hash function") + } + + // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject + // it, and lengths < -2, before we convert to the BoringSSL sentinel values. + if saltLen <= -2 { + return invalidSaltLenErr + } + + // BoringSSL uses sentinel salt length values like we do, but the values don't + // fully match what we use. We both use -1 for salt length equal to hash length, + // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter + // case convert to the BoringSSL version. + if saltLen == 0 { + saltLen = -2 + } + + if pub.withKey(func(key *C.GO_RSA) C.int { + return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.size_t(len(hashed)), + md, nil, C.int(saltLen), base(sig), C.size_t(len(sig))) + }) == 0 { + return fail("RSA_verify_pss_mgf1") + } + return nil +} + +func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) { + if h == 0 { + // No hashing. + var out []byte + var outLen C.size_t + if priv.withKey(func(key *C.GO_RSA) C.int { + out = make([]byte, C._goboringcrypto_RSA_size(key)) + return C._goboringcrypto_RSA_sign_raw(key, &outLen, base(out), C.size_t(len(out)), + base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING) + }) == 0 { + return nil, fail("RSA_sign_raw") + } + return out[:outLen], nil + } + + md := cryptoHashToMD(h) + if md == nil { + return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h))) + } + nid := C._goboringcrypto_EVP_MD_type(md) + var out []byte + var outLen C.uint + if priv.withKey(func(key *C.GO_RSA) C.int { + out = make([]byte, C._goboringcrypto_RSA_size(key)) + return C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), + base(out), &outLen, key) + }) == 0 { + return nil, fail("RSA_sign") + } + return out[:outLen], nil +} + +func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error { + if h == 0 { + var out []byte + var outLen C.size_t + if pub.withKey(func(key *C.GO_RSA) C.int { + out = make([]byte, C._goboringcrypto_RSA_size(key)) + return C._goboringcrypto_RSA_verify_raw(key, &outLen, base(out), + C.size_t(len(out)), base(sig), C.size_t(len(sig)), C.GO_RSA_PKCS1_PADDING) + }) == 0 { + return fail("RSA_verify") + } + if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 { + return fail("RSA_verify") + } + return nil + } + md := cryptoHashToMD(h) + if md == nil { + return errors.New("crypto/rsa: unsupported hash function") + } + nid := C._goboringcrypto_EVP_MD_type(md) + if pub.withKey(func(key *C.GO_RSA) C.int { + return C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)), + base(sig), C.size_t(len(sig)), key) + }) == 0 { + return fail("RSA_verify") + } + return nil +} diff --git a/crypto/internal/boring/sha.go b/crypto/internal/boring/sha.go new file mode 100644 index 00000000000..7a3c00953ef --- /dev/null +++ b/crypto/internal/boring/sha.go @@ -0,0 +1,580 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan + +package boring + +/* +#include "goboringcrypto.h" + +int +_goboringcrypto_gosha1(void *p, size_t n, void *out) +{ + GO_SHA_CTX ctx; + _goboringcrypto_SHA1_Init(&ctx); + return _goboringcrypto_SHA1_Update(&ctx, p, n) && + _goboringcrypto_SHA1_Final(out, &ctx); +} + +int +_goboringcrypto_gosha224(void *p, size_t n, void *out) +{ + GO_SHA256_CTX ctx; + _goboringcrypto_SHA224_Init(&ctx); + return _goboringcrypto_SHA224_Update(&ctx, p, n) && + _goboringcrypto_SHA224_Final(out, &ctx); +} + +int +_goboringcrypto_gosha256(void *p, size_t n, void *out) +{ + GO_SHA256_CTX ctx; + _goboringcrypto_SHA256_Init(&ctx); + return _goboringcrypto_SHA256_Update(&ctx, p, n) && + _goboringcrypto_SHA256_Final(out, &ctx); +} + +int +_goboringcrypto_gosha384(void *p, size_t n, void *out) +{ + GO_SHA512_CTX ctx; + _goboringcrypto_SHA384_Init(&ctx); + return _goboringcrypto_SHA384_Update(&ctx, p, n) && + _goboringcrypto_SHA384_Final(out, &ctx); +} + +int +_goboringcrypto_gosha512(void *p, size_t n, void *out) +{ + GO_SHA512_CTX ctx; + _goboringcrypto_SHA512_Init(&ctx); + return _goboringcrypto_SHA512_Update(&ctx, p, n) && + _goboringcrypto_SHA512_Final(out, &ctx); +} + +*/ +import "C" +import ( + "errors" + "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/internal/byteorder" +) + +// NOTE: The cgo calls in this file are arranged to avoid marking the parameters as escaping. +// To do that, we call noescape (including via addr). +// We must also make sure that the data pointer arguments have the form unsafe.Pointer(&...) +// so that cgo does not annotate them with cgoCheckPointer calls. If it did that, it might look +// beyond the byte slice and find Go pointers in unprocessed parts of a larger allocation. +// To do both of these simultaneously, the idiom is unsafe.Pointer(&*addr(p)), +// where addr returns the base pointer of p, substituting a non-nil pointer for nil, +// and applying a noescape along the way. +// This is all to preserve compatibility with the allocation behavior of the non-boring implementations. + +func SHA1(p []byte) (sum [20]byte) { + if C._goboringcrypto_gosha1(unsafe.Pointer(&*addr(p)), C.size_t(len(p)), unsafe.Pointer(&*addr(sum[:]))) == 0 { + panic("boringcrypto: SHA1 failed") + } + return +} + +func SHA224(p []byte) (sum [28]byte) { + if C._goboringcrypto_gosha224(unsafe.Pointer(&*addr(p)), C.size_t(len(p)), unsafe.Pointer(&*addr(sum[:]))) == 0 { + panic("boringcrypto: SHA224 failed") + } + return +} + +func SHA256(p []byte) (sum [32]byte) { + if C._goboringcrypto_gosha256(unsafe.Pointer(&*addr(p)), C.size_t(len(p)), unsafe.Pointer(&*addr(sum[:]))) == 0 { + panic("boringcrypto: SHA256 failed") + } + return +} + +func SHA384(p []byte) (sum [48]byte) { + if C._goboringcrypto_gosha384(unsafe.Pointer(&*addr(p)), C.size_t(len(p)), unsafe.Pointer(&*addr(sum[:]))) == 0 { + panic("boringcrypto: SHA384 failed") + } + return +} + +func SHA512(p []byte) (sum [64]byte) { + if C._goboringcrypto_gosha512(unsafe.Pointer(&*addr(p)), C.size_t(len(p)), unsafe.Pointer(&*addr(sum[:]))) == 0 { + panic("boringcrypto: SHA512 failed") + } + return +} + +// NewSHA1 returns a new SHA1 hash. +func NewSHA1() hash.Hash { + h := new(sha1Hash) + h.Reset() + return h +} + +type sha1Hash struct { + ctx C.GO_SHA_CTX + out [20]byte +} + +type sha1Ctx struct { + h [5]uint32 + nl, nh uint32 + x [64]byte + nx uint32 +} + +func (h *sha1Hash) noescapeCtx() *C.GO_SHA_CTX { + return (*C.GO_SHA_CTX)(noescape(unsafe.Pointer(&h.ctx))) +} + +func (h *sha1Hash) Reset() { + C._goboringcrypto_SHA1_Init(h.noescapeCtx()) +} + +func (h *sha1Hash) Size() int { return 20 } +func (h *sha1Hash) BlockSize() int { return 64 } +func (h *sha1Hash) Sum(dst []byte) []byte { return h.sum(dst) } + +func (h *sha1Hash) Write(p []byte) (int, error) { + if len(p) > 0 && C._goboringcrypto_SHA1_Update(h.noescapeCtx(), unsafe.Pointer(&*addr(p)), C.size_t(len(p))) == 0 { + panic("boringcrypto: SHA1_Update failed") + } + return len(p), nil +} + +func (h0 *sha1Hash) sum(dst []byte) []byte { + h := *h0 // make copy so future Write+Sum is valid + if C._goboringcrypto_SHA1_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 { + panic("boringcrypto: SHA1_Final failed") + } + return append(dst, h.out[:]...) +} + +const ( + sha1Magic = "sha\x01" + sha1MarshaledSize = len(sha1Magic) + 5*4 + 64 + 8 +) + +func (h *sha1Hash) MarshalBinary() ([]byte, error) { + return h.AppendBinary(make([]byte, 0, sha1MarshaledSize)) +} + +func (h *sha1Hash) AppendBinary(b []byte) ([]byte, error) { + d := (*sha1Ctx)(unsafe.Pointer(&h.ctx)) + b = append(b, sha1Magic...) + b = byteorder.BEAppendUint32(b, d.h[0]) + b = byteorder.BEAppendUint32(b, d.h[1]) + b = byteorder.BEAppendUint32(b, d.h[2]) + b = byteorder.BEAppendUint32(b, d.h[3]) + b = byteorder.BEAppendUint32(b, d.h[4]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-int(d.nx))...) + b = byteorder.BEAppendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29) + return b, nil +} + +func (h *sha1Hash) UnmarshalBinary(b []byte) error { + if len(b) < len(sha1Magic) || string(b[:len(sha1Magic)]) != sha1Magic { + return errors.New("crypto/sha1: invalid hash state identifier") + } + if len(b) != sha1MarshaledSize { + return errors.New("crypto/sha1: invalid hash state size") + } + d := (*sha1Ctx)(unsafe.Pointer(&h.ctx)) + b = b[len(sha1Magic):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, n := consumeUint64(b) + d.nl = uint32(n << 3) + d.nh = uint32(n >> 29) + d.nx = uint32(n) % 64 + return nil +} + +// NewSHA224 returns a new SHA224 hash. +func NewSHA224() hash.Hash { + h := new(sha224Hash) + h.Reset() + return h +} + +type sha224Hash struct { + ctx C.GO_SHA256_CTX + out [224 / 8]byte +} + +func (h *sha224Hash) noescapeCtx() *C.GO_SHA256_CTX { + return (*C.GO_SHA256_CTX)(noescape(unsafe.Pointer(&h.ctx))) +} + +func (h *sha224Hash) Reset() { + C._goboringcrypto_SHA224_Init(h.noescapeCtx()) +} +func (h *sha224Hash) Size() int { return 224 / 8 } +func (h *sha224Hash) BlockSize() int { return 64 } +func (h *sha224Hash) Sum(dst []byte) []byte { return h.sum(dst) } + +func (h *sha224Hash) Write(p []byte) (int, error) { + if len(p) > 0 && C._goboringcrypto_SHA224_Update(h.noescapeCtx(), unsafe.Pointer(&*addr(p)), C.size_t(len(p))) == 0 { + panic("boringcrypto: SHA224_Update failed") + } + return len(p), nil +} + +func (h0 *sha224Hash) sum(dst []byte) []byte { + h := *h0 // make copy so future Write+Sum is valid + if C._goboringcrypto_SHA224_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 { + panic("boringcrypto: SHA224_Final failed") + } + return append(dst, h.out[:]...) +} + +// NewSHA256 returns a new SHA256 hash. +func NewSHA256() hash.Hash { + h := new(sha256Hash) + h.Reset() + return h +} + +type sha256Hash struct { + ctx C.GO_SHA256_CTX + out [256 / 8]byte +} + +func (h *sha256Hash) noescapeCtx() *C.GO_SHA256_CTX { + return (*C.GO_SHA256_CTX)(noescape(unsafe.Pointer(&h.ctx))) +} + +func (h *sha256Hash) Reset() { + C._goboringcrypto_SHA256_Init(h.noescapeCtx()) +} +func (h *sha256Hash) Size() int { return 256 / 8 } +func (h *sha256Hash) BlockSize() int { return 64 } +func (h *sha256Hash) Sum(dst []byte) []byte { return h.sum(dst) } + +func (h *sha256Hash) Write(p []byte) (int, error) { + if len(p) > 0 && C._goboringcrypto_SHA256_Update(h.noescapeCtx(), unsafe.Pointer(&*addr(p)), C.size_t(len(p))) == 0 { + panic("boringcrypto: SHA256_Update failed") + } + return len(p), nil +} + +func (h0 *sha256Hash) sum(dst []byte) []byte { + h := *h0 // make copy so future Write+Sum is valid + if C._goboringcrypto_SHA256_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 { + panic("boringcrypto: SHA256_Final failed") + } + return append(dst, h.out[:]...) +} + +const ( + magic224 = "sha\x02" + magic256 = "sha\x03" + marshaledSize256 = len(magic256) + 8*4 + 64 + 8 +) + +type sha256Ctx struct { + h [8]uint32 + nl, nh uint32 + x [64]byte + nx uint32 +} + +func (h *sha224Hash) MarshalBinary() ([]byte, error) { + return h.AppendBinary(make([]byte, 0, marshaledSize256)) +} + +func (h *sha224Hash) AppendBinary(b []byte) ([]byte, error) { + d := (*sha256Ctx)(unsafe.Pointer(&h.ctx)) + b = append(b, magic224...) + b = byteorder.BEAppendUint32(b, d.h[0]) + b = byteorder.BEAppendUint32(b, d.h[1]) + b = byteorder.BEAppendUint32(b, d.h[2]) + b = byteorder.BEAppendUint32(b, d.h[3]) + b = byteorder.BEAppendUint32(b, d.h[4]) + b = byteorder.BEAppendUint32(b, d.h[5]) + b = byteorder.BEAppendUint32(b, d.h[6]) + b = byteorder.BEAppendUint32(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-int(d.nx))...) + b = byteorder.BEAppendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29) + return b, nil +} + +func (h *sha256Hash) MarshalBinary() ([]byte, error) { + return h.AppendBinary(make([]byte, 0, marshaledSize256)) +} + +func (h *sha256Hash) AppendBinary(b []byte) ([]byte, error) { + d := (*sha256Ctx)(unsafe.Pointer(&h.ctx)) + b = append(b, magic256...) + b = byteorder.BEAppendUint32(b, d.h[0]) + b = byteorder.BEAppendUint32(b, d.h[1]) + b = byteorder.BEAppendUint32(b, d.h[2]) + b = byteorder.BEAppendUint32(b, d.h[3]) + b = byteorder.BEAppendUint32(b, d.h[4]) + b = byteorder.BEAppendUint32(b, d.h[5]) + b = byteorder.BEAppendUint32(b, d.h[6]) + b = byteorder.BEAppendUint32(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-int(d.nx))...) + b = byteorder.BEAppendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29) + return b, nil +} + +func (h *sha224Hash) UnmarshalBinary(b []byte) error { + if len(b) < len(magic224) || string(b[:len(magic224)]) != magic224 { + return errors.New("crypto/sha256: invalid hash state identifier") + } + if len(b) != marshaledSize256 { + return errors.New("crypto/sha256: invalid hash state size") + } + d := (*sha256Ctx)(unsafe.Pointer(&h.ctx)) + b = b[len(magic224):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b, d.h[5] = consumeUint32(b) + b, d.h[6] = consumeUint32(b) + b, d.h[7] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, n := consumeUint64(b) + d.nl = uint32(n << 3) + d.nh = uint32(n >> 29) + d.nx = uint32(n) % 64 + return nil +} + +func (h *sha256Hash) UnmarshalBinary(b []byte) error { + if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 { + return errors.New("crypto/sha256: invalid hash state identifier") + } + if len(b) != marshaledSize256 { + return errors.New("crypto/sha256: invalid hash state size") + } + d := (*sha256Ctx)(unsafe.Pointer(&h.ctx)) + b = b[len(magic256):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b, d.h[5] = consumeUint32(b) + b, d.h[6] = consumeUint32(b) + b, d.h[7] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, n := consumeUint64(b) + d.nl = uint32(n << 3) + d.nh = uint32(n >> 29) + d.nx = uint32(n) % 64 + return nil +} + +// NewSHA384 returns a new SHA384 hash. +func NewSHA384() hash.Hash { + h := new(sha384Hash) + h.Reset() + return h +} + +type sha384Hash struct { + ctx C.GO_SHA512_CTX + out [384 / 8]byte +} + +func (h *sha384Hash) noescapeCtx() *C.GO_SHA512_CTX { + return (*C.GO_SHA512_CTX)(noescape(unsafe.Pointer(&h.ctx))) +} + +func (h *sha384Hash) Reset() { + C._goboringcrypto_SHA384_Init(h.noescapeCtx()) +} +func (h *sha384Hash) Size() int { return 384 / 8 } +func (h *sha384Hash) BlockSize() int { return 128 } +func (h *sha384Hash) Sum(dst []byte) []byte { return h.sum(dst) } + +func (h *sha384Hash) Write(p []byte) (int, error) { + if len(p) > 0 && C._goboringcrypto_SHA384_Update(h.noescapeCtx(), unsafe.Pointer(&*addr(p)), C.size_t(len(p))) == 0 { + panic("boringcrypto: SHA384_Update failed") + } + return len(p), nil +} + +func (h0 *sha384Hash) sum(dst []byte) []byte { + h := *h0 // make copy so future Write+Sum is valid + if C._goboringcrypto_SHA384_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 { + panic("boringcrypto: SHA384_Final failed") + } + return append(dst, h.out[:]...) +} + +// NewSHA512 returns a new SHA512 hash. +func NewSHA512() hash.Hash { + h := new(sha512Hash) + h.Reset() + return h +} + +type sha512Hash struct { + ctx C.GO_SHA512_CTX + out [512 / 8]byte +} + +func (h *sha512Hash) noescapeCtx() *C.GO_SHA512_CTX { + return (*C.GO_SHA512_CTX)(noescape(unsafe.Pointer(&h.ctx))) +} + +func (h *sha512Hash) Reset() { + C._goboringcrypto_SHA512_Init(h.noescapeCtx()) +} +func (h *sha512Hash) Size() int { return 512 / 8 } +func (h *sha512Hash) BlockSize() int { return 128 } +func (h *sha512Hash) Sum(dst []byte) []byte { return h.sum(dst) } + +func (h *sha512Hash) Write(p []byte) (int, error) { + if len(p) > 0 && C._goboringcrypto_SHA512_Update(h.noescapeCtx(), unsafe.Pointer(&*addr(p)), C.size_t(len(p))) == 0 { + panic("boringcrypto: SHA512_Update failed") + } + return len(p), nil +} + +func (h0 *sha512Hash) sum(dst []byte) []byte { + h := *h0 // make copy so future Write+Sum is valid + if C._goboringcrypto_SHA512_Final((*C.uint8_t)(noescape(unsafe.Pointer(&h.out[0]))), h.noescapeCtx()) == 0 { + panic("boringcrypto: SHA512_Final failed") + } + return append(dst, h.out[:]...) +} + +type sha512Ctx struct { + h [8]uint64 + nl, nh uint64 + x [128]byte + nx uint32 +} + +const ( + magic384 = "sha\x04" + magic512_224 = "sha\x05" + magic512_256 = "sha\x06" + magic512 = "sha\x07" + marshaledSize512 = len(magic512) + 8*8 + 128 + 8 +) + +func (h *sha384Hash) MarshalBinary() ([]byte, error) { + return h.AppendBinary(make([]byte, 0, marshaledSize512)) +} + +func (h *sha384Hash) AppendBinary(b []byte) ([]byte, error) { + d := (*sha512Ctx)(unsafe.Pointer(&h.ctx)) + b = append(b, magic384...) + b = byteorder.BEAppendUint64(b, d.h[0]) + b = byteorder.BEAppendUint64(b, d.h[1]) + b = byteorder.BEAppendUint64(b, d.h[2]) + b = byteorder.BEAppendUint64(b, d.h[3]) + b = byteorder.BEAppendUint64(b, d.h[4]) + b = byteorder.BEAppendUint64(b, d.h[5]) + b = byteorder.BEAppendUint64(b, d.h[6]) + b = byteorder.BEAppendUint64(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-int(d.nx))...) + b = byteorder.BEAppendUint64(b, d.nl>>3|d.nh<<61) + return b, nil +} + +func (h *sha512Hash) MarshalBinary() ([]byte, error) { + return h.AppendBinary(make([]byte, 0, marshaledSize512)) +} + +func (h *sha512Hash) AppendBinary(b []byte) ([]byte, error) { + d := (*sha512Ctx)(unsafe.Pointer(&h.ctx)) + b = append(b, magic512...) + b = byteorder.BEAppendUint64(b, d.h[0]) + b = byteorder.BEAppendUint64(b, d.h[1]) + b = byteorder.BEAppendUint64(b, d.h[2]) + b = byteorder.BEAppendUint64(b, d.h[3]) + b = byteorder.BEAppendUint64(b, d.h[4]) + b = byteorder.BEAppendUint64(b, d.h[5]) + b = byteorder.BEAppendUint64(b, d.h[6]) + b = byteorder.BEAppendUint64(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-int(d.nx))...) + b = byteorder.BEAppendUint64(b, d.nl>>3|d.nh<<61) + return b, nil +} + +func (h *sha384Hash) UnmarshalBinary(b []byte) error { + if len(b) < len(magic512) { + return errors.New("crypto/sha512: invalid hash state identifier") + } + if string(b[:len(magic384)]) != magic384 { + return errors.New("crypto/sha512: invalid hash state identifier") + } + if len(b) != marshaledSize512 { + return errors.New("crypto/sha512: invalid hash state size") + } + d := (*sha512Ctx)(unsafe.Pointer(&h.ctx)) + b = b[len(magic512):] + b, d.h[0] = consumeUint64(b) + b, d.h[1] = consumeUint64(b) + b, d.h[2] = consumeUint64(b) + b, d.h[3] = consumeUint64(b) + b, d.h[4] = consumeUint64(b) + b, d.h[5] = consumeUint64(b) + b, d.h[6] = consumeUint64(b) + b, d.h[7] = consumeUint64(b) + b = b[copy(d.x[:], b):] + b, n := consumeUint64(b) + d.nl = n << 3 + d.nh = n >> 61 + d.nx = uint32(n) % 128 + return nil +} + +func (h *sha512Hash) UnmarshalBinary(b []byte) error { + if len(b) < len(magic512) { + return errors.New("crypto/sha512: invalid hash state identifier") + } + if string(b[:len(magic512)]) != magic512 { + return errors.New("crypto/sha512: invalid hash state identifier") + } + if len(b) != marshaledSize512 { + return errors.New("crypto/sha512: invalid hash state size") + } + d := (*sha512Ctx)(unsafe.Pointer(&h.ctx)) + b = b[len(magic512):] + b, d.h[0] = consumeUint64(b) + b, d.h[1] = consumeUint64(b) + b, d.h[2] = consumeUint64(b) + b, d.h[3] = consumeUint64(b) + b, d.h[4] = consumeUint64(b) + b, d.h[5] = consumeUint64(b) + b, d.h[6] = consumeUint64(b) + b, d.h[7] = consumeUint64(b) + b = b[copy(d.x[:], b):] + b, n := consumeUint64(b) + d.nl = n << 3 + d.nh = n >> 61 + d.nx = uint32(n) % 128 + return nil +} + +func consumeUint64(b []byte) ([]byte, uint64) { + return b[8:], byteorder.BEUint64(b) +} + +func consumeUint32(b []byte) ([]byte, uint32) { + return b[4:], byteorder.BEUint32(b) +} diff --git a/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso b/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso new file mode 100644 index 00000000000..6d0aeb83355 Binary files /dev/null and b/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso differ diff --git a/crypto/internal/boring/syso/goboringcrypto_linux_arm64.syso b/crypto/internal/boring/syso/goboringcrypto_linux_arm64.syso new file mode 100644 index 00000000000..23736c82f6b Binary files /dev/null and b/crypto/internal/boring/syso/goboringcrypto_linux_arm64.syso differ diff --git a/crypto/tls/notboring.go b/crypto/internal/boring/syso/syso.go similarity index 54% rename from crypto/tls/notboring.go rename to crypto/internal/boring/syso/syso.go index 39db9ee2341..b3387545e60 100644 --- a/crypto/tls/notboring.go +++ b/crypto/internal/boring/syso/syso.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package tls +//go:build boringcrypto -func needFIPS() bool { return false } +// This package only exists with GOEXPERIMENT=boringcrypto. +// It provides the actual syso file. +package syso diff --git a/crypto/internal/cryptotest/aead.go b/crypto/internal/cryptotest/aead.go index 2a9d4ec0a65..057c10cfdfe 100644 --- a/crypto/internal/cryptotest/aead.go +++ b/crypto/internal/cryptotest/aead.go @@ -7,8 +7,9 @@ package cryptotest import ( "bytes" "fmt" - "github.com/runZeroInc/excrypto/crypto/cipher" "testing" + + "github.com/runZeroInc/excrypto/crypto/cipher" ) var lengths = []int{0, 156, 8192, 8193, 8208} @@ -208,10 +209,12 @@ func TestAEAD(t *testing.T, mAEAD MakeAEAD) { t.Errorf("Seal alters dst instead of appending; got %s, want %s", truncateHex(out[:len(prefix)]), truncateHex(prefix)) } - ciphertext := out[len(prefix):] - // Check that the appended ciphertext wasn't affected by the prefix - if expectedCT := sealMsg(t, aead, nil, nonce, plaintext, addData); !bytes.Equal(ciphertext, expectedCT) { - t.Errorf("Seal behavior affected by pre-existing data in dst; got %s, want %s", truncateHex(ciphertext), truncateHex(expectedCT)) + if isDeterministic(aead) { + ciphertext := out[len(prefix):] + // Check that the appended ciphertext wasn't affected by the prefix + if expectedCT := sealMsg(t, aead, nil, nonce, plaintext, addData); !bytes.Equal(ciphertext, expectedCT) { + t.Errorf("Seal behavior affected by pre-existing data in dst; got %s, want %s", truncateHex(ciphertext), truncateHex(expectedCT)) + } } } }) @@ -254,7 +257,9 @@ func TestAEAD(t *testing.T, mAEAD MakeAEAD) { }) t.Run("WrongNonce", func(t *testing.T) { - + if aead.NonceSize() == 0 { + t.Skip("AEAD does not use a nonce") + } // Test all combinations of plaintext and additional data lengths. for _, ptLen := range lengths { for _, adLen := range lengths { @@ -372,6 +377,18 @@ func sealMsg(t *testing.T, aead cipher.AEAD, ciphertext, nonce, plaintext, addDa return ciphertext } +func isDeterministic(aead cipher.AEAD) bool { + // Check if the AEAD is deterministic by checking if the same plaintext + // encrypted with the same nonce and additional data produces the same + // ciphertext. + nonce := make([]byte, aead.NonceSize()) + addData := []byte("additional data") + plaintext := []byte("plaintext") + ciphertext1 := aead.Seal(nil, nonce, plaintext, addData) + ciphertext2 := aead.Seal(nil, nonce, plaintext, addData) + return bytes.Equal(ciphertext1, ciphertext2) +} + // Helper function to Open and authenticate ciphertext. Checks that Open // doesn't error (assuming ciphertext was well-formed with corresponding nonce // and additional data). diff --git a/crypto/internal/cryptotest/allocations.go b/crypto/internal/cryptotest/allocations.go new file mode 100644 index 00000000000..5a73c96baa4 --- /dev/null +++ b/crypto/internal/cryptotest/allocations.go @@ -0,0 +1,37 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptotest + +import "testing" + +// SkipTestAllocations skips the test if there are any factors that interfere +// with allocation optimizations. +func SkipTestAllocations(t *testing.T) { + /* + // Go+BoringCrypto uses cgo. + if boring.Enabled { + t.Skip("skipping allocations test with BoringCrypto") + } + + // The sanitizers sometimes cause allocations. + if race.Enabled || msan.Enabled || asan.Enabled { + t.Skip("skipping allocations test with sanitizers") + } + + // The plan9 crypto/rand allocates. + if runtime.GOOS == "plan9" { + t.Skip("skipping allocations test on plan9") + } + + // s390x deviates from other assembly implementations and is very hard to + // test due to the lack of LUCI builders. See #67307. + if runtime.GOARCH == "s390x" { + t.Skip("skipping allocations test on s390x") + } + + // Some APIs rely on inliner and devirtualization to allocate on the stack. + testenv.SkipIfOptimizationOff(t) + */ +} diff --git a/crypto/internal/cryptotest/block.go b/crypto/internal/cryptotest/block.go index a60b39258de..66207e3fc29 100644 --- a/crypto/internal/cryptotest/block.go +++ b/crypto/internal/cryptotest/block.go @@ -6,8 +6,9 @@ package cryptotest import ( "bytes" - "github.com/runZeroInc/excrypto/crypto/cipher" "testing" + + "github.com/runZeroInc/excrypto/crypto/cipher" ) type MakeBlock func(key []byte) (cipher.Block, error) diff --git a/crypto/internal/cryptotest/blockmode.go b/crypto/internal/cryptotest/blockmode.go index 6f0bd1ef8a5..86ff3464ca0 100644 --- a/crypto/internal/cryptotest/blockmode.go +++ b/crypto/internal/cryptotest/blockmode.go @@ -6,8 +6,9 @@ package cryptotest import ( "bytes" - "github.com/runZeroInc/excrypto/crypto/cipher" "testing" + + "github.com/runZeroInc/excrypto/crypto/cipher" ) // MakeBlockMode returns a cipher.BlockMode instance. @@ -60,6 +61,19 @@ func testBlockMode(t *testing.T, bm MakeBlockMode, b cipher.Block, iv []byte) { mustPanic(t, "IV length must equal block size", func() { bm(b, iv) }) }) + t.Run("EmptyInput", func(t *testing.T) { + rng := newRandReader(t) + + src, dst := make([]byte, blockSize), make([]byte, blockSize) + rng.Read(dst) + before := bytes.Clone(dst) + + bm(b, iv).CryptBlocks(dst, src[:0]) + if !bytes.Equal(dst, before) { + t.Errorf("CryptBlocks modified dst on empty input; got %x, want %x", dst, before) + } + }) + t.Run("AlterInput", func(t *testing.T) { rng := newRandReader(t) diff --git a/crypto/internal/cryptotest/fetchmodule.go b/crypto/internal/cryptotest/fetchmodule.go new file mode 100644 index 00000000000..d5b9284a193 --- /dev/null +++ b/crypto/internal/cryptotest/fetchmodule.go @@ -0,0 +1,60 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptotest + +import ( + "bytes" + "encoding/json" + "os" + "os/exec" + "testing" + + "github.com/runZeroInc/excrypto/internal/testenv" +) + +// FetchModule fetches the module at the given version and returns the directory +// containing its source tree. It skips the test if fetching modules is not +// possible in this environment. +func FetchModule(t *testing.T, module, version string) string { + testenv.MustHaveExternalNetwork(t) + goTool := testenv.GoToolPath(t) + + // If the default GOMODCACHE doesn't exist, use a temporary directory + // instead. (For example, run.bash sets GOPATH=/nonexist-gopath.) + out, err := testenv.Command(t, goTool, "env", "GOMODCACHE").Output() + if err != nil { + t.Errorf("%s env GOMODCACHE: %v\n%s", goTool, err, out) + if ee, ok := err.(*exec.ExitError); ok { + t.Logf("%s", ee.Stderr) + } + t.FailNow() + } + modcacheOk := false + if gomodcache := string(bytes.TrimSpace(out)); gomodcache != "" { + if _, err := os.Stat(gomodcache); err == nil { + modcacheOk = true + } + } + if !modcacheOk { + t.Setenv("GOMODCACHE", t.TempDir()) + // Allow t.TempDir() to clean up subdirectories. + t.Setenv("GOFLAGS", os.Getenv("GOFLAGS")+" -modcacherw") + } + + t.Logf("fetching %s@%s\n", module, version) + + output, err := testenv.Command(t, goTool, "mod", "download", "-json", module+"@"+version).CombinedOutput() + if err != nil { + t.Fatalf("failed to download %s@%s: %s\n%s\n", module, version, err, output) + } + var j struct { + Dir string + } + if err := json.Unmarshal(output, &j); err != nil { + t.Fatalf("failed to parse 'go mod download': %s\n%s\n", err, output) + } + + return j.Dir +} diff --git a/crypto/internal/cryptotest/hash.go b/crypto/internal/cryptotest/hash.go index f03623dfa26..0a52e9dfd22 100644 --- a/crypto/internal/cryptotest/hash.go +++ b/crypto/internal/cryptotest/hash.go @@ -1,16 +1,16 @@ -// Copyright 2024 The Go Authors. All rights reserved. +// Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package cryptotest import ( - "bytes" - "hash" "io" "math/rand" "testing" "time" + + "github.com/runZeroInc/excrypto/hash" ) type MakeHash func() hash.Hash @@ -18,168 +18,13 @@ type MakeHash func() hash.Hash // TestHash performs a set of tests on hash.Hash implementations, checking the // documented requirements of Write, Sum, Reset, Size, and BlockSize. func TestHash(t *testing.T, mh MakeHash) { - - // Test that Sum returns an appended digest matching output of Size - t.Run("SumAppend", func(t *testing.T) { - h := mh() - rng := newRandReader(t) - - emptyBuff := []byte("") - shortBuff := []byte("a") - longBuff := make([]byte, h.BlockSize()+1) - rng.Read(longBuff) - - // Set of example strings to append digest to - prefixes := [][]byte{nil, emptyBuff, shortBuff, longBuff} - - // Go to each string and check digest gets appended to and is correct size. - for _, prefix := range prefixes { - h.Reset() - - sum := getSum(t, h, prefix) // Append new digest to prefix - - // Check that Sum didn't alter the prefix - if !bytes.Equal(sum[:len(prefix)], prefix) { - t.Errorf("Sum alters passed buffer instead of appending; got %x, want %x", sum[:len(prefix)], prefix) - } - - // Check that the appended sum wasn't affected by the prefix - if expectedSum := getSum(t, h, nil); !bytes.Equal(sum[len(prefix):], expectedSum) { - t.Errorf("Sum behavior affected by data in the input buffer; got %x, want %x", sum[len(prefix):], expectedSum) - } - - // Check size of append - if got, want := len(sum)-len(prefix), h.Size(); got != want { - t.Errorf("Sum appends number of bytes != Size; got %v , want %v", got, want) - } + /* + if boring.Enabled || fips140.Version() == "v1.0" { + testhash.TestHashWithoutClone(t, testhash.MakeHash(mh)) + return } - }) - - // Test that Hash.Write never returns error. - t.Run("WriteWithoutError", func(t *testing.T) { - h := mh() - rng := newRandReader(t) - - emptySlice := []byte("") - shortSlice := []byte("a") - longSlice := make([]byte, h.BlockSize()+1) - rng.Read(longSlice) - - // Set of example strings to append digest to - slices := [][]byte{emptySlice, shortSlice, longSlice} - - for _, slice := range slices { - writeToHash(t, h, slice) // Writes and checks Write doesn't error - } - }) - - t.Run("ResetState", func(t *testing.T) { - h := mh() - rng := newRandReader(t) - - emptySum := getSum(t, h, nil) - - // Write to hash and then Reset it and see if Sum is same as emptySum - writeEx := make([]byte, h.BlockSize()) - rng.Read(writeEx) - writeToHash(t, h, writeEx) - h.Reset() - resetSum := getSum(t, h, nil) - - if !bytes.Equal(emptySum, resetSum) { - t.Errorf("Reset hash yields different Sum than new hash; got %x, want %x", emptySum, resetSum) - } - }) - - // Check that Write isn't reading from beyond input slice's bounds - t.Run("OutOfBoundsRead", func(t *testing.T) { - h := mh() - blockSize := h.BlockSize() - rng := newRandReader(t) - - msg := make([]byte, blockSize) - rng.Read(msg) - writeToHash(t, h, msg) - expectedDigest := getSum(t, h, nil) // Record control digest - - h.Reset() - - // Make a buffer with msg in the middle and data on either end - buff := make([]byte, blockSize*3) - endOfPrefix, startOfSuffix := blockSize, blockSize*2 - - copy(buff[endOfPrefix:startOfSuffix], msg) - rng.Read(buff[:endOfPrefix]) - rng.Read(buff[startOfSuffix:]) - - writeToHash(t, h, buff[endOfPrefix:startOfSuffix]) - testDigest := getSum(t, h, nil) - - if !bytes.Equal(testDigest, expectedDigest) { - t.Errorf("Write affected by data outside of input slice bounds; got %x, want %x", testDigest, expectedDigest) - } - }) - - // Test that multiple calls to Write is stateful - t.Run("StatefulWrite", func(t *testing.T) { - h := mh() - rng := newRandReader(t) - - prefix, suffix := make([]byte, h.BlockSize()), make([]byte, h.BlockSize()) - rng.Read(prefix) - rng.Read(suffix) - - // Write prefix then suffix sequentially and record resulting hash - writeToHash(t, h, prefix) - writeToHash(t, h, suffix) - serialSum := getSum(t, h, nil) - - h.Reset() - - // Write prefix and suffix at the same time and record resulting hash - writeToHash(t, h, append(prefix, suffix...)) - compositeSum := getSum(t, h, nil) - - // Check that sequential writing results in the same as writing all at once - if !bytes.Equal(compositeSum, serialSum) { - t.Errorf("two successive Write calls resulted in a different Sum than a single one; got %x, want %x", compositeSum, serialSum) - } - }) -} - -// Helper function for writing. Verifies that Write does not error. -func writeToHash(t *testing.T, h hash.Hash, p []byte) { - t.Helper() - - before := make([]byte, len(p)) - copy(before, p) - - n, err := h.Write(p) - if err != nil || n != len(p) { - t.Errorf("Write returned error; got (%v, %v), want (nil, %v)", err, n, len(p)) - } - - if !bytes.Equal(p, before) { - t.Errorf("Write modified input slice; got %x, want %x", p, before) - } -} - -// Helper function for getting Sum. Checks that Sum doesn't change hash state. -func getSum(t *testing.T, h hash.Hash, buff []byte) []byte { - t.Helper() - - testBuff := make([]byte, len(buff)) - copy(testBuff, buff) - - sum := h.Sum(buff) - testSum := h.Sum(testBuff) - - // Check that Sum doesn't change underlying hash state - if !bytes.Equal(sum, testSum) { - t.Errorf("successive calls to Sum yield different results; got %x, want %x", sum, testSum) - } - - return sum + testhash.TestHash(t, testhash.MakeHash(mh)) + */ } func newRandReader(t *testing.T) io.Reader { diff --git a/crypto/internal/cryptotest/implementations.go b/crypto/internal/cryptotest/implementations.go new file mode 100644 index 00000000000..ad7d84d4cc2 --- /dev/null +++ b/crypto/internal/cryptotest/implementations.go @@ -0,0 +1,60 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptotest + +import ( + "runtime" + "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/impl" + "github.com/runZeroInc/excrypto/internal/goarch" + "github.com/runZeroInc/excrypto/internal/testenv" +) + +// TestAllImplementations runs the provided test function with each available +// implementation of the package registered with crypto/internal/impl. If there +// are no alternative implementations for pkg, f is invoked directly once. +func TestAllImplementations(t *testing.T, pkg string, f func(t *testing.T)) { + // BoringCrypto bypasses the multiple Go implementations. + if boring.Enabled { + f(t) + return + } + + impls := impl.List(pkg) + if len(impls) == 0 { + f(t) + return + } + + t.Cleanup(func() { impl.Reset(pkg) }) + + for _, name := range impls { + if available := impl.Select(pkg, name); available { + t.Run(name, f) + } else { + t.Run(name, func(t *testing.T) { + // Report an error if we're on the most capable builder for the + // architecture and the builder can't test this implementation. + flagship := runtime.GOOS == "linux" && goarch.GOARCH != "arm64" || + runtime.GOOS == "darwin" && goarch.GOARCH == "arm64" + if testenv.Builder() != "" && flagship { + if name == "SHA-NI" { + t.Skip("known issue, see golang.org/issue/69592") + } + t.Error("builder doesn't support CPU features needed to test this implementation") + } else { + t.Skip("implementation not supported") + } + }) + } + + } + + // Test the generic implementation. + impl.Select(pkg, "") + t.Run("Base", f) +} diff --git a/crypto/internal/cryptotest/methods.go b/crypto/internal/cryptotest/methods.go new file mode 100644 index 00000000000..9105eb30aa0 --- /dev/null +++ b/crypto/internal/cryptotest/methods.go @@ -0,0 +1,62 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptotest + +import ( + "fmt" + "reflect" + "slices" + "testing" +) + +// NoExtraMethods checks that the concrete type of *ms has no exported methods +// beyond the methods of the interface type of *ms, and any others specified in +// the allowed list. +// +// These methods are accessible through interface upgrades, so they end up part +// of the API even if undocumented per Hyrum's Law. +// +// ms must be a pointer to a non-nil interface. +func NoExtraMethods(t *testing.T, ms interface{}, allowed ...string) { + t.Helper() + extraMethods, err := extraMethods(ms) + if err != nil { + t.Fatal(err) + } + for _, m := range extraMethods { + if slices.Contains(allowed, m) { + continue + } + t.Errorf("unexpected method %q", m) + } +} + +func extraMethods(ip interface{}) ([]string, error) { + v := reflect.ValueOf(ip) + if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Interface || v.Elem().IsNil() { + return nil, fmt.Errorf("argument must be a pointer to a non-nil interface") + } + + interfaceType := v.Elem().Type() + concreteType := v.Elem().Elem().Type() + + interfaceMethods := make(map[string]bool) + for i := range interfaceType.NumMethod() { + interfaceMethods[interfaceType.Method(i).Name] = true + } + + var extraMethods []string + for i := range concreteType.NumMethod() { + m := concreteType.Method(i) + if !m.IsExported() { + continue + } + if !interfaceMethods[m.Name] { + extraMethods = append(extraMethods, m.Name) + } + } + + return extraMethods, nil +} diff --git a/crypto/internal/cryptotest/stream.go b/crypto/internal/cryptotest/stream.go index 6bd2a69f919..42e485219cf 100644 --- a/crypto/internal/cryptotest/stream.go +++ b/crypto/internal/cryptotest/stream.go @@ -7,10 +7,11 @@ package cryptotest import ( "bytes" "fmt" - "github.com/runZeroInc/excrypto/crypto/cipher" - "github.com/runZeroInc/excrypto/crypto/subtle" "strings" "testing" + + "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/subtle" ) // Each test is executed with each of the buffer lengths in bufLens. @@ -86,6 +87,19 @@ func TestStream(t *testing.T, ms MakeStream) { }) }) + t.Run("EmptyInput", func(t *testing.T) { + rng := newRandReader(t) + + src, dst := make([]byte, 100), make([]byte, 100) + rng.Read(dst) + before := bytes.Clone(dst) + + ms().XORKeyStream(dst, src[:0]) + if !bytes.Equal(dst, before) { + t.Errorf("XORKeyStream modified dst on empty input; got %s, want %s", truncateHex(dst), truncateHex(before)) + } + }) + t.Run("AlterInput", func(t *testing.T) { rng := newRandReader(t) src, dst, before := make([]byte, bufCap), make([]byte, bufCap), make([]byte, bufCap) diff --git a/crypto/internal/edwards25519/field/_asm/go.mod b/crypto/internal/edwards25519/field/_asm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/edwards25519/field/_asm/go.sum b/crypto/internal/edwards25519/field/_asm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/edwards25519/field/fe_arm64.go b/crypto/internal/edwards25519/field/fe_arm64.go deleted file mode 100644 index 05c7cedd4e9..00000000000 --- a/crypto/internal/edwards25519/field/fe_arm64.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package field - -//go:noescape -func carryPropagate(v *Element) - -func (v *Element) carryPropagate() *Element { - carryPropagate(v) - return v -} diff --git a/crypto/internal/edwards25519/field/fe_arm64.s b/crypto/internal/edwards25519/field/fe_arm64.s deleted file mode 100644 index ae207dae43e..00000000000 --- a/crypto/internal/edwards25519/field/fe_arm64.s +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -#include "textflag.h" - -// carryPropagate works exactly like carryPropagateGeneric and uses the -// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but -// avoids loading R0-R4 twice and uses LDP and STP. -// -// See https://golang.org/issues/43145 for the main compiler issue. -// -// func carryPropagate(v *Element) -TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 - MOVD v+0(FP), R20 - - LDP 0(R20), (R0, R1) - LDP 16(R20), (R2, R3) - MOVD 32(R20), R4 - - AND $0x7ffffffffffff, R0, R10 - AND $0x7ffffffffffff, R1, R11 - AND $0x7ffffffffffff, R2, R12 - AND $0x7ffffffffffff, R3, R13 - AND $0x7ffffffffffff, R4, R14 - - ADD R0>>51, R11, R11 - ADD R1>>51, R12, R12 - ADD R2>>51, R13, R13 - ADD R3>>51, R14, R14 - // R4>>51 * 19 + R10 -> R10 - LSR $51, R4, R21 - MOVD $19, R22 - MADD R22, R10, R21, R10 - - STP (R10, R11), 0(R20) - STP (R12, R13), 16(R20) - MOVD R14, 32(R20) - - RET diff --git a/crypto/internal/edwards25519/field/fe_arm64_noasm.go b/crypto/internal/edwards25519/field/fe_arm64_noasm.go deleted file mode 100644 index 6b9e06a6e82..00000000000 --- a/crypto/internal/edwards25519/field/fe_arm64_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !arm64 || purego - -package field - -func (v *Element) carryPropagate() *Element { - return v.carryPropagateGeneric() -} diff --git a/crypto/internal/entropy/entropy.go b/crypto/internal/entropy/entropy.go new file mode 100644 index 00000000000..108d69639e9 --- /dev/null +++ b/crypto/internal/entropy/entropy.go @@ -0,0 +1,28 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package entropy provides the passive entropy source for the FIPS 140-3 +// module. It is only used in FIPS mode by [crypto/internal/fips140/drbg.Read]. +// +// This complies with IG 9.3.A, Additional Comment 12, which until January 1, +// 2026 allows new modules to meet an [earlier version] of Resolution 2(b): +// "A software module that contains an approved DRBG that receives a LOAD +// command (or its logical equivalent) with entropy obtained from [...] inside +// the physical perimeter of the operational environment of the module [...]." +// +// Distributions that have their own SP 800-90B entropy source should replace +// this package with their own implementation. +// +// [earlier version]: https://csrc.nist.gov/CSRC/media/Projects/cryptographic-module-validation-program/documents/IG%209.3.A%20Resolution%202b%5BMarch%2026%202024%5D.pdf +package entropy + +// Depleted notifies the entropy source that the entropy in the module is +// "depleted" and provides the callback for the LOAD command. +func Depleted(LOAD func(*[48]byte)) { + /* + var entropy [48]byte + sysrand.Read(entropy[:]) + LOAD(&entropy) + */ +} diff --git a/crypto/internal/fips140/aes/_asm/ctr/ctr_amd64_asm.go b/crypto/internal/fips140/aes/_asm/ctr/ctr_amd64_asm.go new file mode 100644 index 00000000000..35e1d8aeb62 --- /dev/null +++ b/crypto/internal/fips140/aes/_asm/ctr/ctr_amd64_asm.go @@ -0,0 +1,127 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "sync" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +//go:generate go run . -out ../../ctr_amd64.s + +func main() { + Package("crypto/aes") + ConstraintExpr("!purego") + + ctrBlocks(1) + ctrBlocks(2) + ctrBlocks(4) + ctrBlocks(8) + + Generate() +} + +func ctrBlocks(numBlocks int) { + Implement(fmt.Sprintf("ctrBlocks%dAsm", numBlocks)) + + rounds := Load(Param("nr"), GP64()) + xk := Load(Param("xk"), GP64()) + dst := Load(Param("dst"), GP64()) + src := Load(Param("src"), GP64()) + ivlo := Load(Param("ivlo"), GP64()) + ivhi := Load(Param("ivhi"), GP64()) + + bswap := XMM() + MOVOU(bswapMask(), bswap) + + blocks := make([]VecVirtual, 0, numBlocks) + + // Lay out counter block plaintext. + for i := 0; i < numBlocks; i++ { + x := XMM() + blocks = append(blocks, x) + + MOVQ(ivlo, x) + PINSRQ(Imm(1), ivhi, x) + PSHUFB(bswap, x) + if i < numBlocks-1 { + ADDQ(Imm(1), ivlo) + ADCQ(Imm(0), ivhi) + } + } + + // Initial key add. + aesRoundStart(blocks, Mem{Base: xk}) + ADDQ(Imm(16), xk) + + // Branch based on the number of rounds. + SUBQ(Imm(12), rounds) + JE(LabelRef("enc192")) + JB(LabelRef("enc128")) + + // Two extra rounds for 256-bit keys. + aesRound(blocks, Mem{Base: xk}) + aesRound(blocks, Mem{Base: xk}.Offset(16)) + ADDQ(Imm(32), xk) + + // Two extra rounds for 192-bit keys. + Label("enc192") + aesRound(blocks, Mem{Base: xk}) + aesRound(blocks, Mem{Base: xk}.Offset(16)) + ADDQ(Imm(32), xk) + + // 10 rounds for 128-bit keys (with special handling for the final round). + Label("enc128") + for i := 0; i < 9; i++ { + aesRound(blocks, Mem{Base: xk}.Offset(16*i)) + } + aesRoundLast(blocks, Mem{Base: xk}.Offset(16*9)) + + // XOR state with src and write back to dst. + for i, b := range blocks { + x := XMM() + + MOVUPS(Mem{Base: src}.Offset(16*i), x) + PXOR(b, x) + MOVUPS(x, Mem{Base: dst}.Offset(16*i)) + } + + RET() +} + +func aesRoundStart(blocks []VecVirtual, k Mem) { + x := XMM() + MOVUPS(k, x) + for _, b := range blocks { + PXOR(x, b) + } +} + +func aesRound(blocks []VecVirtual, k Mem) { + x := XMM() + MOVUPS(k, x) + for _, b := range blocks { + AESENC(x, b) + } +} + +func aesRoundLast(blocks []VecVirtual, k Mem) { + x := XMM() + MOVUPS(k, x) + for _, b := range blocks { + AESENCLAST(x, b) + } +} + +var bswapMask = sync.OnceValue(func() Mem { + bswapMask := GLOBL("bswapMask", NOPTR|RODATA) + DATA(0x00, U64(0x08090a0b0c0d0e0f)) + DATA(0x08, U64(0x0001020304050607)) + return bswapMask +}) diff --git a/crypto/internal/fips140/aes/_asm/ctr/go.mod b/crypto/internal/fips140/aes/_asm/ctr/go.mod new file mode 100644 index 00000000000..5d97cd7f4e6 --- /dev/null +++ b/crypto/internal/fips140/aes/_asm/ctr/go.mod @@ -0,0 +1,11 @@ +module crypto/aes/_asm/ctr + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/aes/_asm/ctr/go.sum b/crypto/internal/fips140/aes/_asm/ctr/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/aes/_asm/ctr/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/aes/_asm/standard/asm_amd64.go b/crypto/internal/fips140/aes/_asm/standard/aes_amd64.go similarity index 98% rename from crypto/aes/_asm/standard/asm_amd64.go rename to crypto/internal/fips140/aes/_asm/standard/aes_amd64.go index cd192af6d72..44e0a79289c 100644 --- a/crypto/aes/_asm/standard/asm_amd64.go +++ b/crypto/internal/fips140/aes/_asm/standard/aes_amd64.go @@ -14,10 +14,10 @@ import ( . "github.com/mmcloughlin/avo/reg" ) -//go:generate go run . -out ../../asm_amd64.s -pkg aes +//go:generate go run . -out ../../aes_amd64.s func main() { - Package("github.com/runZeroInc/excrypto/crypto/aes") + Package("crypto/aes") ConstraintExpr("!purego") encryptBlockAsm() decryptBlockAsm() diff --git a/crypto/internal/fips140/aes/_asm/standard/go.mod b/crypto/internal/fips140/aes/_asm/standard/go.mod new file mode 100644 index 00000000000..f1329b7290a --- /dev/null +++ b/crypto/internal/fips140/aes/_asm/standard/go.mod @@ -0,0 +1,11 @@ +module crypto/aes/_asm/standard + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/aes/_asm/standard/go.sum b/crypto/internal/fips140/aes/_asm/standard/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/aes/_asm/standard/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/internal/fips140/aes/aes.go b/crypto/internal/fips140/aes/aes.go new file mode 100644 index 00000000000..54d82303a46 --- /dev/null +++ b/crypto/internal/fips140/aes/aes.go @@ -0,0 +1,132 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "strconv" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" +) + +// BlockSize is the AES block size in bytes. +const BlockSize = 16 + +// A Block is an instance of AES using a particular key. +// It is safe for concurrent use. +type Block struct { + block +} + +// blockExpanded is the block type used for all architectures except s390x, +// which feeds the raw key directly to its instructions. +type blockExpanded struct { + rounds int + // Round keys, where only the first (rounds + 1) × (128 ÷ 32) words are used. + enc [60]uint32 + dec [60]uint32 +} + +const ( + // AES-128 has 128-bit keys, 10 rounds, and uses 11 128-bit round keys + // (11×128÷32 = 44 32-bit words). + + // AES-192 has 192-bit keys, 12 rounds, and uses 13 128-bit round keys + // (13×128÷32 = 52 32-bit words). + + // AES-256 has 256-bit keys, 14 rounds, and uses 15 128-bit round keys + // (15×128÷32 = 60 32-bit words). + + aes128KeySize = 16 + aes192KeySize = 24 + aes256KeySize = 32 + + aes128Rounds = 10 + aes192Rounds = 12 + aes256Rounds = 14 +) + +// roundKeysSize returns the number of uint32 of c.end or c.dec that are used. +func (b *blockExpanded) roundKeysSize() int { + return (b.rounds + 1) * (128 / 32) +} + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) +} + +// New creates and returns a new [cipher.Block] implementation. +// The key argument should be the AES key, either 16, 24, or 32 bytes to select +// AES-128, AES-192, or AES-256. +func New(key []byte) (*Block, error) { + // This call is outline to let the allocation happen on the parent stack. + return newOutlined(&Block{}, key) +} + +// newOutlined is marked go:noinline to avoid it inlining into New, and making New +// too complex to inline itself. +// +//go:noinline +func newOutlined(b *Block, key []byte) (*Block, error) { + switch len(key) { + case aes128KeySize, aes192KeySize, aes256KeySize: + default: + return nil, KeySizeError(len(key)) + } + return newBlock(b, key), nil +} + +func newBlockExpanded(c *blockExpanded, key []byte) { + switch len(key) { + case aes128KeySize: + c.rounds = aes128Rounds + case aes192KeySize: + c.rounds = aes192Rounds + case aes256KeySize: + c.rounds = aes256Rounds + } + expandKeyGeneric(c, key) +} + +func (c *Block) BlockSize() int { return BlockSize } + +func (c *Block) Encrypt(dst, src []byte) { + // AES-ECB is not approved in FIPS 140-3 mode. + fips140.RecordNonApproved() + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + encryptBlock(c, dst, src) +} + +func (c *Block) Decrypt(dst, src []byte) { + // AES-ECB is not approved in FIPS 140-3 mode. + fips140.RecordNonApproved() + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + decryptBlock(c, dst, src) +} + +// EncryptBlockInternal applies the AES encryption function to one block. +// +// It is an internal function meant only for the gcm package. +func EncryptBlockInternal(c *Block, dst, src []byte) { + encryptBlock(c, dst, src) +} diff --git a/crypto/aes/asm_amd64.s b/crypto/internal/fips140/aes/aes_amd64.s similarity index 100% rename from crypto/aes/asm_amd64.s rename to crypto/internal/fips140/aes/aes_amd64.s diff --git a/crypto/aes/asm_arm64.s b/crypto/internal/fips140/aes/aes_arm64.s similarity index 96% rename from crypto/aes/asm_arm64.s rename to crypto/internal/fips140/aes/aes_arm64.s index 2bf5bee2b59..1e885595404 100644 --- a/crypto/aes/asm_arm64.s +++ b/crypto/internal/fips140/aes/aes_arm64.s @@ -22,14 +22,14 @@ TEXT ·encryptBlockAsm(SB),NOSPLIT,$0 CMP $12, R9 BLT enc128 - BEQ enc196 + BEQ enc192 enc256: VLD1.P 32(R10), [V1.B16, V2.B16] AESE V1.B16, V0.B16 AESMC V0.B16, V0.B16 AESE V2.B16, V0.B16 AESMC V0.B16, V0.B16 -enc196: +enc192: VLD1.P 32(R10), [V3.B16, V4.B16] AESE V3.B16, V0.B16 AESMC V0.B16, V0.B16 @@ -73,14 +73,14 @@ TEXT ·decryptBlockAsm(SB),NOSPLIT,$0 CMP $12, R9 BLT dec128 - BEQ dec196 + BEQ dec192 dec256: VLD1.P 32(R10), [V1.B16, V2.B16] AESD V1.B16, V0.B16 AESIMC V0.B16, V0.B16 AESD V2.B16, V0.B16 AESIMC V0.B16, V0.B16 -dec196: +dec192: VLD1.P 32(R10), [V3.B16, V4.B16] AESD V3.B16, V0.B16 AESIMC V0.B16, V0.B16 @@ -134,7 +134,7 @@ TEXT ·expandKeyAsm(SB),NOSPLIT,$0 MOVW $0x1b, R14 ks128Loop: VMOV R7, V2.S[0] - WORD $0x4E030042 // TBL V3.B16, [V2.B16], V2.B16 + VTBL V3.B16, [V2.B16], V2.B16 AESE V0.B16, V2.B16 // Use AES to compute the SBOX EORW R13, R4 LSLW $1, R13 // Compute next Rcon @@ -180,7 +180,7 @@ ks192: ks192Loop: STPW.P (R6, R7), 8(R10) VMOV R7, V2.S[0] - WORD $0x4E030042 //TBL V3.B16, [V2.B16], V2.B16 + VTBL V3.B16, [V2.B16], V2.B16 AESE V0.B16, V2.B16 EORW R13, R2 LSLW $1, R13 @@ -233,7 +233,7 @@ ks256Loop: STPW.P (R4, R5), 8(R10) STPW.P (R6, R7), 8(R10) VMOV R7, V2.S[0] - WORD $0x4E030042 //TBL V3.B16, [V2.B16], V2.B16 + VTBL V3.B16, [V2.B16], V2.B16 AESE V0.B16, V2.B16 EORW R13, R0 LSLW $1, R13 @@ -244,7 +244,7 @@ ks256Loop: EORW R1, R2 EORW R2, R3 VMOV R3, V2.S[0] - WORD $0x4E040042 //TBL V3.B16, [V2.B16], V2.B16 + VTBL V4.B16, [V2.B16], V2.B16 AESE V0.B16, V2.B16 VMOV V2.S[0], R9 EORW R9, R4 diff --git a/crypto/internal/fips140/aes/aes_asm.go b/crypto/internal/fips140/aes/aes_asm.go new file mode 100644 index 00000000000..03b1f3adf7c --- /dev/null +++ b/crypto/internal/fips140/aes/aes_asm.go @@ -0,0 +1,96 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (amd64 || arm64 || ppc64 || ppc64le) && !purego + +package aes + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +//go:noescape +func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape +func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape +func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) + +var supportsAES = cpu.X86HasAES && cpu.X86HasSSE41 && cpu.X86HasSSSE3 || + cpu.ARM64HasAES || cpu.PPC64 || cpu.PPC64le + +func init() { + if cpu.AMD64 { + impl.Register("aes", "AES-NI", &supportsAES) + } + if cpu.ARM64 { + impl.Register("aes", "Armv8.0", &supportsAES) + } + if cpu.PPC64 || cpu.PPC64le { + // The POWER architecture doesn't have a way to turn off AES support + // at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG + // knob for that. It's intentionally only checked at init() time, to + // avoid the performance overhead of checking it every time. + if godebug.Value("#ppc64aes") == "off" { + supportsAES = false + } + impl.Register("aes", "POWER8", &supportsAES) + } +} + +// checkGenericIsExpected is called by the variable-time implementation to make +// sure it is not used when hardware support is available. It shouldn't happen, +// but this way it's more evidently correct. +func checkGenericIsExpected() { + if supportsAES { + panic("crypto/aes: internal error: using generic implementation despite hardware support") + } +} + +type block struct { + blockExpanded +} + +func newBlock(c *Block, key []byte) *Block { + switch len(key) { + case aes128KeySize: + c.rounds = aes128Rounds + case aes192KeySize: + c.rounds = aes192Rounds + case aes256KeySize: + c.rounds = aes256Rounds + } + if supportsAES { + expandKeyAsm(c.rounds, &key[0], &c.enc[0], &c.dec[0]) + } else { + expandKeyGeneric(&c.blockExpanded, key) + } + return c +} + +// EncryptionKeySchedule is used from the GCM implementation to access the +// precomputed AES key schedule, to pass to the assembly implementation. +func EncryptionKeySchedule(c *Block) []uint32 { + return c.enc[:c.roundKeysSize()] +} + +func encryptBlock(c *Block, dst, src []byte) { + if supportsAES { + encryptBlockAsm(c.rounds, &c.enc[0], &dst[0], &src[0]) + } else { + encryptBlockGeneric(&c.blockExpanded, dst, src) + } +} + +func decryptBlock(c *Block, dst, src []byte) { + if supportsAES { + decryptBlockAsm(c.rounds, &c.dec[0], &dst[0], &src[0]) + } else { + decryptBlockGeneric(&c.blockExpanded, dst, src) + } +} diff --git a/crypto/aes/block.go b/crypto/internal/fips140/aes/aes_generic.go similarity index 80% rename from crypto/aes/block.go rename to crypto/internal/fips140/aes/aes_generic.go index 81824db9665..5ea5da3f2dd 100644 --- a/crypto/aes/block.go +++ b/crypto/internal/fips140/aes/aes_generic.go @@ -36,15 +36,18 @@ package aes -import "github.com/runZeroInc/excrypto/internal/byteorder" +import "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" // Encrypt one block from src into dst, using the expanded key xk. -func encryptBlockGo(xk []uint32, dst, src []byte) { +func encryptBlockGeneric(c *blockExpanded, dst, src []byte) { + checkGenericIsExpected() + xk := c.enc[:] + _ = src[15] // early bounds check - s0 := byteorder.BeUint32(src[0:4]) - s1 := byteorder.BeUint32(src[4:8]) - s2 := byteorder.BeUint32(src[8:12]) - s3 := byteorder.BeUint32(src[12:16]) + s0 := byteorder.BEUint32(src[0:4]) + s1 := byteorder.BEUint32(src[4:8]) + s2 := byteorder.BEUint32(src[8:12]) + s3 := byteorder.BEUint32(src[12:16]) // First round just XORs input with key. s0 ^= xk[0] @@ -53,11 +56,9 @@ func encryptBlockGo(xk []uint32, dst, src []byte) { s3 ^= xk[3] // Middle rounds shuffle using tables. - // Number of rounds is set by length of expanded key. - nr := len(xk)/4 - 2 // - 2: one above, one more below k := 4 var t0, t1, t2, t3 uint32 - for r := 0; r < nr; r++ { + for r := 0; r < c.rounds-1; r++ { t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)] t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)] t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)] @@ -78,19 +79,22 @@ func encryptBlockGo(xk []uint32, dst, src []byte) { s3 ^= xk[k+3] _ = dst[15] // early bounds check - byteorder.BePutUint32(dst[0:4], s0) - byteorder.BePutUint32(dst[4:8], s1) - byteorder.BePutUint32(dst[8:12], s2) - byteorder.BePutUint32(dst[12:16], s3) + byteorder.BEPutUint32(dst[0:4], s0) + byteorder.BEPutUint32(dst[4:8], s1) + byteorder.BEPutUint32(dst[8:12], s2) + byteorder.BEPutUint32(dst[12:16], s3) } // Decrypt one block from src into dst, using the expanded key xk. -func decryptBlockGo(xk []uint32, dst, src []byte) { +func decryptBlockGeneric(c *blockExpanded, dst, src []byte) { + checkGenericIsExpected() + xk := c.dec[:] + _ = src[15] // early bounds check - s0 := byteorder.BeUint32(src[0:4]) - s1 := byteorder.BeUint32(src[4:8]) - s2 := byteorder.BeUint32(src[8:12]) - s3 := byteorder.BeUint32(src[12:16]) + s0 := byteorder.BEUint32(src[0:4]) + s1 := byteorder.BEUint32(src[4:8]) + s2 := byteorder.BEUint32(src[8:12]) + s3 := byteorder.BEUint32(src[12:16]) // First round just XORs input with key. s0 ^= xk[0] @@ -99,11 +103,9 @@ func decryptBlockGo(xk []uint32, dst, src []byte) { s3 ^= xk[3] // Middle rounds shuffle using tables. - // Number of rounds is set by length of expanded key. - nr := len(xk)/4 - 2 // - 2: one above, one more below k := 4 var t0, t1, t2, t3 uint32 - for r := 0; r < nr; r++ { + for r := 0; r < c.rounds-1; r++ { t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)] t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)] t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)] @@ -124,10 +126,10 @@ func decryptBlockGo(xk []uint32, dst, src []byte) { s3 ^= xk[k+3] _ = dst[15] // early bounds check - byteorder.BePutUint32(dst[0:4], s0) - byteorder.BePutUint32(dst[4:8], s1) - byteorder.BePutUint32(dst[8:12], s2) - byteorder.BePutUint32(dst[12:16], s3) + byteorder.BEPutUint32(dst[0:4], s0) + byteorder.BEPutUint32(dst[4:8], s1) + byteorder.BEPutUint32(dst[8:12], s2) + byteorder.BEPutUint32(dst[12:16], s3) } // Apply sbox0 to each byte in w. @@ -143,38 +145,37 @@ func rotw(w uint32) uint32 { return w<<8 | w>>24 } // Key expansion algorithm. See FIPS-197, Figure 11. // Their rcon[i] is our powx[i-1] << 24. -func expandKeyGo(key []byte, enc, dec []uint32) { +func expandKeyGeneric(c *blockExpanded, key []byte) { + checkGenericIsExpected() + // Encryption key setup. var i int nk := len(key) / 4 for i = 0; i < nk; i++ { - enc[i] = byteorder.BeUint32(key[4*i:]) + c.enc[i] = byteorder.BEUint32(key[4*i:]) } - for ; i < len(enc); i++ { - t := enc[i-1] + for ; i < c.roundKeysSize(); i++ { + t := c.enc[i-1] if i%nk == 0 { t = subw(rotw(t)) ^ (uint32(powx[i/nk-1]) << 24) } else if nk > 6 && i%nk == 4 { t = subw(t) } - enc[i] = enc[i-nk] ^ t + c.enc[i] = c.enc[i-nk] ^ t } // Derive decryption key from encryption key. // Reverse the 4-word round key sets from enc to produce dec. // All sets but the first and last get the MixColumn transform applied. - if dec == nil { - return - } - n := len(enc) + n := c.roundKeysSize() for i := 0; i < n; i += 4 { ei := n - i - 4 for j := 0; j < 4; j++ { - x := enc[ei+j] + x := c.enc[ei+j] if i > 0 && i+4 < n { x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]] } - dec[i+j] = x + c.dec[i+j] = x } } } diff --git a/crypto/internal/fips140/aes/aes_noasm.go b/crypto/internal/fips140/aes/aes_noasm.go new file mode 100644 index 00000000000..8ba540273e3 --- /dev/null +++ b/crypto/internal/fips140/aes/aes_noasm.go @@ -0,0 +1,26 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !s390x && !ppc64 && !ppc64le && !arm64) || purego + +package aes + +type block struct { + blockExpanded +} + +func newBlock(c *Block, key []byte) *Block { + newBlockExpanded(&c.blockExpanded, key) + return c +} + +func encryptBlock(c *Block, dst, src []byte) { + encryptBlockGeneric(&c.blockExpanded, dst, src) +} + +func decryptBlock(c *Block, dst, src []byte) { + decryptBlockGeneric(&c.blockExpanded, dst, src) +} + +func checkGenericIsExpected() {} diff --git a/crypto/aes/asm_ppc64x.s b/crypto/internal/fips140/aes/aes_ppc64x.s similarity index 76% rename from crypto/aes/asm_ppc64x.s rename to crypto/internal/fips140/aes/aes_ppc64x.s index 5a2b210920e..4c95dd21527 100644 --- a/crypto/aes/asm_ppc64x.s +++ b/crypto/internal/fips140/aes/aes_ppc64x.s @@ -74,6 +74,7 @@ GLOBL ·rcon(SB), RODATA, $80 #define P8_LXVB16X(RA,RB,VT) LXVB16X (RA+RB), VT #define P8_STXVB16X(VS,RA,RB) STXVB16X VS, (RA+RB) #define XXBRD_ON_LE(VA,VT) XXBRD VA, VT +#define SETUP_ESPERM(rtmp) # else // On POWER8/ppc64le, emulate the POWER9 instructions by loading unaligned // doublewords and byte-swapping each doubleword to emulate BE load/stores. @@ -89,11 +90,17 @@ GLOBL ·rcon(SB), RODATA, $80 #define XXBRD_ON_LE(VA,VT) \ VPERM VA, VA, ESPERM, VT +// Setup byte-swapping permute value in ESPERM for POWER9 instruction +// emulation macros. +#define SETUP_ESPERM(rtmp) \ + MOVD $·rcon(SB), rtmp \ + LVX (rtmp), ESPERM # endif // defined(GOPPC64_power9) #else #define P8_LXVB16X(RA,RB,VT) LXVD2X (RA+RB), VT #define P8_STXVB16X(VS,RA,RB) STXVD2X VS, (RA+RB) #define XXBRD_ON_LE(VA, VT) +#define SETUP_ESPERM(rtmp) #endif // defined(GOARCH_ppc64le) // func setEncryptKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) @@ -313,10 +320,7 @@ TEXT ·encryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 MOVD xk+8(FP), R5 // Key pointer MOVD dst+16(FP), R3 // Dest pointer MOVD src+24(FP), R4 // Src pointer -#ifdef NEEDS_ESPERM - MOVD $·rcon(SB), R7 - LVX (R7), ESPERM // Permute value for P8_ macros. -#endif + SETUP_ESPERM(R7) // Set CR{1,2,3}EQ to hold the key size information. CMPU R6, $10, CR1 @@ -408,10 +412,7 @@ TEXT ·decryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 MOVD xk+8(FP), R5 // Key pointer MOVD dst+16(FP), R3 // Dest pointer MOVD src+24(FP), R4 // Src pointer -#ifdef NEEDS_ESPERM - MOVD $·rcon(SB), R7 - LVX (R7), ESPERM // Permute value for P8_ macros. -#endif + SETUP_ESPERM(R7) // Set CR{1,2,3}EQ to hold the key size information. CMPU R6, $10, CR1 @@ -626,10 +627,7 @@ TEXT ·cryptBlocksChain(SB), NOSPLIT|NOFRAME, $0 MOVD enc+40(FP), ENC MOVD nr+48(FP), ROUNDS -#ifdef NEEDS_ESPERM - MOVD $·rcon(SB), R11 - LVX (R11), ESPERM // Permute value for P8_ macros. -#endif + SETUP_ESPERM(R11) // Assume len > 0 && len % blockSize == 0. CMPW ENC, $0 @@ -673,3 +671,221 @@ Lcbc_dec: P8_STXVB16X(IVEC, IVP, R0) CLEAR_KEYS() RET + + +#define DO1_CIPHER(iv0, keyv, key, op) \ + LXVD2X (key), keyv \ + ADD $16, key \ + op iv0, keyv, iv0 + +#define DO2_CIPHER(iv0, iv1, keyv, key, op) \ + DO1_CIPHER(iv0, keyv, key, op) \ + op iv1, keyv, iv1 + +#define DO4_CIPHER(iv0, iv1, iv2, iv3, keyv, key, op) \ + DO2_CIPHER(iv0, iv1, keyv, key, op) \ + op iv2, keyv, iv2 \ + op iv3, keyv, iv3 + +#define DO8_CIPHER(iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7, keyv, key, op) \ + DO4_CIPHER(iv0, iv1, iv2, iv3, keyv, key, op) \ + op iv4, keyv, iv4 \ + op iv5, keyv, iv5 \ + op iv6, keyv, iv6 \ + op iv7, keyv, iv7 + +#define XOR_STORE(src, iv, dstp, dstpoff) \ + XXLXOR src, iv, V8 \ + P8_STXVB16X(V8,dstp,dstpoff) + +//func ctrBlocks1Asm(nr int, xk *[60]uint32, dst, src *[1 * BlockSize]byte, ivlo, ivhi uint64) +TEXT ·ctrBlocks1Asm(SB), NOSPLIT|NOFRAME, $0 + +#define CTRBLOCK_PROLOGUE \ + MOVD nr+0(FP), R3 \ + MOVD xk+8(FP), R4 \ + MOVD dst+16(FP), R5 \ + MOVD src+24(FP), R6 \ + MOVD ivlo+32(FP), R8 \ + MOVD ivhi+40(FP), R9 \ + CMP R3, $12, CR1 \ + MTVSRD R8, V0 \ + MTVSRD R9, V1 \ + XXPERMDI V1, V0, $0, V0 \ + SETUP_ESPERM(R8) + + CTRBLOCK_PROLOGUE + + DO1_CIPHER(V0,V8,R4,VXOR) + + BEQ CR1, key_12 + BLT CR1, key_10 +key_14: + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) +key_12: + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) +key_10: + P8_LXVB16X(R6,R0,V9) + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHER) + + DO1_CIPHER(V0,V8,R4,VCIPHER) + DO1_CIPHER(V0,V8,R4,VCIPHERLAST) + + XOR_STORE(V9,V0,R5,R0) + RET + +//func ctrBlocks2Asm(nr int, xk *[60]uint32, dst, src *[2 * BlockSize]byte, ivlo, ivhi uint64) +TEXT ·ctrBlocks2Asm(SB), NOSPLIT|NOFRAME, $0 + CTRBLOCK_PROLOGUE + + XXLEQV V8, V8, V8 // V0 is -1 + VSUBUQM V0, V8, V1 // Vi = IV + i (as IV - (-1)) + + DO2_CIPHER(V0,V1,V8,R4,VXOR) + + BEQ CR1, key_12 + BLT CR1, key_10 +key_14: + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) +key_12: + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) +key_10: + P8_LXVB16X(R6,R0,V9) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + MOVD $16, R8 + P8_LXVB16X(R6,R8,V10) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHER) + DO2_CIPHER(V0,V1,V8,R4,VCIPHERLAST) + + XOR_STORE(V9,V0,R5,R0) + XOR_STORE(V10,V1,R5,R8) + + RET + +//func ctrBlocks4Asm(nr int, xk *[60]uint32, dst, src *[4 * BlockSize]byte, ivlo, ivhi uint64) +TEXT ·ctrBlocks4Asm(SB), NOSPLIT|NOFRAME, $0 + CTRBLOCK_PROLOGUE + + XXLEQV V8, V8, V8 // V0 is -1 + VSUBUQM V0, V8, V1 // Vi = IV + i (as IV - (-1)) + VSUBUQM V1, V8, V2 + VSUBUQM V2, V8, V3 + + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VXOR) + + BEQ CR1, key_12 + BLT CR1, key_10 +key_14: + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) +key_12: + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) +key_10: + P8_LXVB16X(R6,R0,V9) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + MOVD $16, R8 + P8_LXVB16X(R6,R8,V10) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + MOVD $32, R9 + P8_LXVB16X(R6,R9,V11) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + MOVD $48, R10 + P8_LXVB16X(R6,R10,V12) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHER) + DO4_CIPHER(V0,V1,V2,V3,V8,R4,VCIPHERLAST) + + XOR_STORE(V9,V0,R5,R0) + XOR_STORE(V10,V1,R5,R8) + XOR_STORE(V11,V2,R5,R9) + XOR_STORE(V12,V3,R5,R10) + + RET + +//func ctrBlocks8Asm(nr int, xk *[60]uint32, dst, src *[8 * BlockSize]byte, ivlo, ivhi uint64) +TEXT ·ctrBlocks8Asm(SB), NOSPLIT|NOFRAME, $0 + CTRBLOCK_PROLOGUE + + XXLEQV V8, V8, V8 // V8 is -1 + VSUBUQM V0, V8, V1 // Vi = IV + i (as IV - (-1)) + VADDUQM V8, V8, V9 // V9 is -2 + + VSUBUQM V0, V9, V2 + VSUBUQM V1, V9, V3 + VSUBUQM V2, V9, V4 + VSUBUQM V3, V9, V5 + VSUBUQM V4, V9, V6 + VSUBUQM V5, V9, V7 + + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VXOR) + + BEQ CR1, key_12 + BLT CR1, key_10 +key_14: + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) +key_12: + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) +key_10: + P8_LXVB16X(R6,R0,V9) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $16, R8 + P8_LXVB16X(R6,R8,V10) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $32, R9 + P8_LXVB16X(R6,R9,V11) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $48, R10 + P8_LXVB16X(R6,R10,V12) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $64, R11 + P8_LXVB16X(R6,R11,V13) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $80, R12 + P8_LXVB16X(R6,R12,V14) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $96, R14 + P8_LXVB16X(R6,R14,V15) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + MOVD $112, R15 + P8_LXVB16X(R6,R15,V16) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHER) + DO8_CIPHER(V0,V1,V2,V3,V4,V5,V6,V7,V8,R4,VCIPHERLAST) + + XOR_STORE(V9,V0,R5,R0) + XOR_STORE(V10,V1,R5,R8) + XOR_STORE(V11,V2,R5,R9) + XOR_STORE(V12,V3,R5,R10) + XOR_STORE(V13,V4,R5,R11) + XOR_STORE(V14,V5,R5,R12) + XOR_STORE(V15,V6,R5,R14) + XOR_STORE(V16,V7,R5,R15) + + RET + diff --git a/crypto/internal/fips140/aes/aes_s390x.go b/crypto/internal/fips140/aes/aes_s390x.go new file mode 100644 index 00000000000..409b89d3f42 --- /dev/null +++ b/crypto/internal/fips140/aes/aes_s390x.go @@ -0,0 +1,99 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package aes + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +type code int + +// Function codes for the cipher message family of instructions. +const ( + aes128 code = 18 + aes192 code = 19 + aes256 code = 20 +) + +type block struct { + function code // code for cipher message instruction + key []byte // key (128, 192 or 256 bits) + storage [32]byte // array backing key slice + + fallback *blockExpanded +} + +// cryptBlocks invokes the cipher message (KM) instruction with +// the given function code. This is equivalent to AES in ECB +// mode. The length must be a multiple of BlockSize (16). +// +//go:noescape +func cryptBlocks(c code, key, dst, src *byte, length int) + +var supportsAES = cpu.S390XHasAES && cpu.S390XHasAESCBC + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf + impl.Register("aes", "CPACF", &supportsAES) +} + +func checkGenericIsExpected() { + if supportsAES { + panic("crypto/aes: internal error: using generic implementation despite hardware support") + } +} + +func newBlock(c *Block, key []byte) *Block { + if !supportsAES { + c.fallback = &blockExpanded{} + newBlockExpanded(c.fallback, key) + return c + } + + switch len(key) { + case aes128KeySize: + c.function = aes128 + case aes192KeySize: + c.function = aes192 + case aes256KeySize: + c.function = aes256 + } + c.key = c.storage[:len(key)] + copy(c.key, key) + return c +} + +// BlockFunction returns the function code for the block cipher. +// It is used by the GCM implementation to invoke the KMA instruction. +func BlockFunction(c *Block) int { + return int(c.function) +} + +// BlockKey returns the key for the block cipher. +// It is used by the GCM implementation to invoke the KMA instruction. +func BlockKey(c *Block) []byte { + return c.key +} + +func encryptBlock(c *Block, dst, src []byte) { + if c.fallback != nil { + encryptBlockGeneric(c.fallback, dst, src) + } else { + cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) + } +} + +func decryptBlock(c *Block, dst, src []byte) { + if c.fallback != nil { + decryptBlockGeneric(c.fallback, dst, src) + } else { + // The decrypt function code is equal to the function code + 128. + cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) + } +} diff --git a/crypto/internal/fips140/aes/aes_s390x.s b/crypto/internal/fips140/aes/aes_s390x.s new file mode 100644 index 00000000000..5a60dd03b16 --- /dev/null +++ b/crypto/internal/fips140/aes/aes_s390x.s @@ -0,0 +1,39 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func cryptBlocks(c code, key, dst, src *byte, length int) +TEXT ·cryptBlocks(SB),NOSPLIT,$0-40 + MOVD key+8(FP), R1 + MOVD dst+16(FP), R2 + MOVD src+24(FP), R4 + MOVD length+32(FP), R5 + MOVD c+0(FP), R0 +loop: + KM R2, R4 // cipher message (KM) + BVS loop // branch back if interrupted + XOR R0, R0 + RET + +// func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) +TEXT ·cryptBlocksChain(SB),NOSPLIT,$48-48 + LA params-48(SP), R1 + MOVD iv+8(FP), R8 + MOVD key+16(FP), R9 + MVC $16, 0(R8), 0(R1) // move iv into params + MVC $32, 0(R9), 16(R1) // move key into params + MOVD dst+24(FP), R2 + MOVD src+32(FP), R4 + MOVD length+40(FP), R5 + MOVD c+0(FP), R0 +loop: + KMC R2, R4 // cipher message with chaining (KMC) + BVS loop // branch back if interrupted + XOR R0, R0 + MVC $16, 0(R1), 0(R8) // update iv + RET + diff --git a/crypto/internal/fips140/aes/aes_test.go b/crypto/internal/fips140/aes/aes_test.go new file mode 100644 index 00000000000..35046389135 --- /dev/null +++ b/crypto/internal/fips140/aes/aes_test.go @@ -0,0 +1,120 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import "testing" + +// See const.go for overview of math here. + +// Test that powx is initialized correctly. +// (Can adapt this code to generate it too.) +func TestPowx(t *testing.T) { + p := 1 + for i := 0; i < len(powx); i++ { + if powx[i] != byte(p) { + t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p) + } + p <<= 1 + if p&0x100 != 0 { + p ^= poly + } + } +} + +// Multiply b and c as GF(2) polynomials modulo poly +func mul(b, c uint32) uint32 { + i := b + j := c + s := uint32(0) + for k := uint32(1); k < 0x100 && j != 0; k <<= 1 { + // Invariant: k == 1<>8 + } + } +} + +// Test that decryption tables are correct. +// (Can adapt this code to generate them too.) +func TestTd(t *testing.T) { + for i := 0; i < 256; i++ { + s := uint32(sbox1[i]) + s9 := mul(s, 0x9) + sb := mul(s, 0xb) + sd := mul(s, 0xd) + se := mul(s, 0xe) + w := se<<24 | s9<<16 | sd<<8 | sb + td := [][256]uint32{td0, td1, td2, td3} + for j := 0; j < 4; j++ { + if x := td[j][i]; x != w { + t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w) + } + w = w<<24 | w>>8 + } + } +} diff --git a/crypto/internal/fips140/aes/cast.go b/crypto/internal/fips140/aes/cast.go new file mode 100644 index 00000000000..75b833ec666 --- /dev/null +++ b/crypto/internal/fips140/aes/cast.go @@ -0,0 +1,47 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + fips140.CAST("AES-CBC", func() error { + key := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + iv := [16]byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + plaintext := []byte{ + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + } + ciphertext := []byte{ + 0xdf, 0x76, 0x26, 0x4b, 0xd3, 0xb2, 0xc4, 0x8d, + 0x40, 0xa2, 0x6e, 0x7a, 0xc4, 0xff, 0xbd, 0x35, + } + b, err := New(key) + if err != nil { + return err + } + buf := make([]byte, 16) + NewCBCEncrypter(b, iv).CryptBlocks(buf, plaintext) + if !bytes.Equal(buf, ciphertext) { + return errors.New("unexpected result") + } + NewCBCDecrypter(b, iv).CryptBlocks(buf, ciphertext) + if !bytes.Equal(buf, plaintext) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/aes/cbc.go b/crypto/internal/fips140/aes/cbc.go new file mode 100644 index 00000000000..b3e38cf72a2 --- /dev/null +++ b/crypto/internal/fips140/aes/cbc.go @@ -0,0 +1,130 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" +) + +type CBCEncrypter struct { + b Block + iv [BlockSize]byte +} + +// NewCBCEncrypter returns a [cipher.BlockMode] which encrypts in cipher block +// chaining mode, using the given Block. +func NewCBCEncrypter(b *Block, iv [BlockSize]byte) *CBCEncrypter { + return &CBCEncrypter{b: *b, iv: iv} +} + +func (c *CBCEncrypter) BlockSize() int { return BlockSize } + +func (c *CBCEncrypter) CryptBlocks(dst, src []byte) { + if len(src)%BlockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if alias.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + fips140.RecordApproved() + if len(src) == 0 { + return + } + cryptBlocksEnc(&c.b, &c.iv, dst, src) +} + +func (x *CBCEncrypter) SetIV(iv []byte) { + if len(iv) != len(x.iv) { + panic("cipher: incorrect length IV") + } + copy(x.iv[:], iv) +} + +func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { + iv := civ[:] + for len(src) > 0 { + // Write the xor to dst, then encrypt in place. + subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv) + encryptBlock(b, dst[:BlockSize], dst[:BlockSize]) + + // Move to the next block with this block as the next iv. + iv = dst[:BlockSize] + src = src[BlockSize:] + dst = dst[BlockSize:] + } + + // Save the iv for the next CryptBlocks call. + copy(civ[:], iv) +} + +type CBCDecrypter struct { + b Block + iv [BlockSize]byte +} + +// NewCBCDecrypter returns a [cipher.BlockMode] which decrypts in cipher block +// chaining mode, using the given Block. +func NewCBCDecrypter(b *Block, iv [BlockSize]byte) *CBCDecrypter { + return &CBCDecrypter{b: *b, iv: iv} +} + +func (c *CBCDecrypter) BlockSize() int { return BlockSize } + +func (c *CBCDecrypter) CryptBlocks(dst, src []byte) { + if len(src)%BlockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if alias.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + fips140.RecordApproved() + if len(src) == 0 { + return + } + cryptBlocksDec(&c.b, &c.iv, dst, src) +} + +func (x *CBCDecrypter) SetIV(iv []byte) { + if len(iv) != len(x.iv) { + panic("cipher: incorrect length IV") + } + copy(x.iv[:], iv) +} + +func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { + // For each block, we need to xor the decrypted data with the previous + // block's ciphertext (the iv). To avoid making a copy each time, we loop + // over the blocks backwards. + end := len(src) + start := end - BlockSize + prev := start - BlockSize + + // Copy the last block of ciphertext as the IV of the next call. + iv := *civ + copy(civ[:], src[start:end]) + + for start >= 0 { + decryptBlock(b, dst[start:end], src[start:end]) + + if start > 0 { + subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) + } else { + // The first block is special because it uses the saved iv. + subtle.XORBytes(dst[start:end], dst[start:end], iv[:]) + } + + end -= BlockSize + start -= BlockSize + prev -= BlockSize + } +} diff --git a/crypto/internal/fips140/aes/cbc_noasm.go b/crypto/internal/fips140/aes/cbc_noasm.go new file mode 100644 index 00000000000..fd10c2e99fe --- /dev/null +++ b/crypto/internal/fips140/aes/cbc_noasm.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!s390x && !ppc64 && !ppc64le) || purego + +package aes + +func cryptBlocksEnc(b *Block, civ *[BlockSize]byte, dst, src []byte) { + cryptBlocksEncGeneric(b, civ, dst, src) +} + +func cryptBlocksDec(b *Block, civ *[BlockSize]byte, dst, src []byte) { + cryptBlocksDecGeneric(b, civ, dst, src) +} diff --git a/crypto/internal/fips140/aes/cbc_ppc64x.go b/crypto/internal/fips140/aes/cbc_ppc64x.go new file mode 100644 index 00000000000..460bae3d497 --- /dev/null +++ b/crypto/internal/fips140/aes/cbc_ppc64x.go @@ -0,0 +1,31 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64 || ppc64le) && !purego + +package aes + +// cryptBlocksChain invokes the cipher message identifying encrypt or decrypt. +// +//go:noescape +func cryptBlocksChain(src, dst *byte, length int, key *uint32, iv *byte, enc int, nr int) + +const cbcEncrypt = 1 +const cbcDecrypt = 0 + +func cryptBlocksEnc(b *Block, civ *[BlockSize]byte, dst, src []byte) { + if !supportsAES { + cryptBlocksEncGeneric(b, civ, dst, src) + } else { + cryptBlocksChain(&src[0], &dst[0], len(src), &b.enc[0], &civ[0], cbcEncrypt, b.rounds) + } +} + +func cryptBlocksDec(b *Block, civ *[BlockSize]byte, dst, src []byte) { + if !supportsAES { + cryptBlocksDecGeneric(b, civ, dst, src) + } else { + cryptBlocksChain(&src[0], &dst[0], len(src), &b.dec[0], &civ[0], cbcDecrypt, b.rounds) + } +} diff --git a/crypto/internal/fips140/aes/cbc_s390x.go b/crypto/internal/fips140/aes/cbc_s390x.go new file mode 100644 index 00000000000..b4eb997a60c --- /dev/null +++ b/crypto/internal/fips140/aes/cbc_s390x.go @@ -0,0 +1,30 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package aes + +// cryptBlocksChain invokes the cipher message with chaining (KMC) instruction +// with the given function code. The length must be a multiple of BlockSize (16). +// +//go:noescape +func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) + +func cryptBlocksEnc(b *Block, civ *[BlockSize]byte, dst, src []byte) { + if b.fallback != nil { + cryptBlocksEncGeneric(b, civ, dst, src) + return + } + cryptBlocksChain(b.function, &civ[0], &b.key[0], &dst[0], &src[0], len(src)) +} + +func cryptBlocksDec(b *Block, civ *[BlockSize]byte, dst, src []byte) { + if b.fallback != nil { + cryptBlocksDecGeneric(b, civ, dst, src) + return + } + // Decrypt function code is encrypt + 128. + cryptBlocksChain(b.function+128, &civ[0], &b.key[0], &dst[0], &src[0], len(src)) +} diff --git a/crypto/aes/const.go b/crypto/internal/fips140/aes/const.go similarity index 97% rename from crypto/aes/const.go rename to crypto/internal/fips140/aes/const.go index 4eca4b9aff8..3ecc922b5a4 100644 --- a/crypto/aes/const.go +++ b/crypto/internal/fips140/aes/const.go @@ -2,15 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package aes implements AES encryption (formerly Rijndael), as defined in -// U.S. Federal Information Processing Standards Publication 197. -// -// The AES operations in this package are not implemented using constant-time algorithms. -// An exception is when running on systems with enabled hardware support for AES -// that makes these operations constant-time. Examples include amd64 systems using AES-NI -// extensions and s390x systems using Message-Security-Assist extensions. -// On such systems, when the result of NewCipher is passed to cipher.NewGCM, -// the GHASH operation used by GCM is also constant-time. package aes // This file contains AES constants - 8720 bytes of initialized data. diff --git a/crypto/internal/fips140/aes/ctr.go b/crypto/internal/fips140/aes/ctr.go new file mode 100644 index 00000000000..699a30e07ff --- /dev/null +++ b/crypto/internal/fips140/aes/ctr.go @@ -0,0 +1,149 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +type CTR struct { + b Block + ivlo, ivhi uint64 // start counter as 64-bit limbs + offset uint64 // for XORKeyStream only +} + +func NewCTR(b *Block, iv []byte) *CTR { + // Allocate the CTR here, in an easily inlineable function, so + // the allocation can be done in the caller's stack frame + // instead of the heap. See issue 70499. + c := newCTR(b, iv) + return &c +} +func newCTR(b *Block, iv []byte) CTR { + if len(iv) != BlockSize { + panic("bad IV length") + } + + return CTR{ + b: *b, + ivlo: byteorder.BEUint64(iv[8:16]), + ivhi: byteorder.BEUint64(iv[0:8]), + offset: 0, + } +} + +func (c *CTR) XORKeyStream(dst, src []byte) { + c.XORKeyStreamAt(dst, src, c.offset) + + var carry uint64 + c.offset, carry = bits.Add64(c.offset, uint64(len(src)), 0) + if carry != 0 { + panic("crypto/aes: counter overflow") + } +} + +// RoundToBlock is used by CTR_DRBG, which discards the rightmost unused bits at +// each request. It rounds the offset up to the next block boundary. +func RoundToBlock(c *CTR) { + if remainder := c.offset % BlockSize; remainder != 0 { + var carry uint64 + c.offset, carry = bits.Add64(c.offset, BlockSize-remainder, 0) + if carry != 0 { + panic("crypto/aes: counter overflow") + } + } +} + +// XORKeyStreamAt behaves like XORKeyStream but keeps no state, and instead +// seeks into the keystream by the given bytes offset from the start (ignoring +// any XORKetStream calls). This allows for random access into the keystream, up +// to 16 EiB from the start. +func (c *CTR) XORKeyStreamAt(dst, src []byte, offset uint64) { + if len(dst) < len(src) { + panic("crypto/aes: len(dst) < len(src)") + } + dst = dst[:len(src)] + if alias.InexactOverlap(dst, src) { + panic("crypto/aes: invalid buffer overlap") + } + fips140.RecordApproved() + + ivlo, ivhi := add128(c.ivlo, c.ivhi, offset/BlockSize) + + if blockOffset := offset % BlockSize; blockOffset != 0 { + // We have a partial block at the beginning. + var in, out [BlockSize]byte + copy(in[blockOffset:], src) + ctrBlocks1(&c.b, &out, &in, ivlo, ivhi) + n := copy(dst, out[blockOffset:]) + src = src[n:] + dst = dst[n:] + ivlo, ivhi = add128(ivlo, ivhi, 1) + } + + for len(src) >= 8*BlockSize { + ctrBlocks8(&c.b, (*[8 * BlockSize]byte)(dst), (*[8 * BlockSize]byte)(src), ivlo, ivhi) + src = src[8*BlockSize:] + dst = dst[8*BlockSize:] + ivlo, ivhi = add128(ivlo, ivhi, 8) + } + + // The tail can have at most 7 = 4 + 2 + 1 blocks. + if len(src) >= 4*BlockSize { + ctrBlocks4(&c.b, (*[4 * BlockSize]byte)(dst), (*[4 * BlockSize]byte)(src), ivlo, ivhi) + src = src[4*BlockSize:] + dst = dst[4*BlockSize:] + ivlo, ivhi = add128(ivlo, ivhi, 4) + } + if len(src) >= 2*BlockSize { + ctrBlocks2(&c.b, (*[2 * BlockSize]byte)(dst), (*[2 * BlockSize]byte)(src), ivlo, ivhi) + src = src[2*BlockSize:] + dst = dst[2*BlockSize:] + ivlo, ivhi = add128(ivlo, ivhi, 2) + } + if len(src) >= 1*BlockSize { + ctrBlocks1(&c.b, (*[1 * BlockSize]byte)(dst), (*[1 * BlockSize]byte)(src), ivlo, ivhi) + src = src[1*BlockSize:] + dst = dst[1*BlockSize:] + ivlo, ivhi = add128(ivlo, ivhi, 1) + } + + if len(src) != 0 { + // We have a partial block at the end. + var in, out [BlockSize]byte + copy(in[:], src) + ctrBlocks1(&c.b, &out, &in, ivlo, ivhi) + copy(dst, out[:]) + } +} + +// Each ctrBlocksN function XORs src with N blocks of counter keystream, and +// stores it in dst. src is loaded in full before storing dst, so they can +// overlap even inexactly. The starting counter value is passed in as a pair of +// little-endian 64-bit integers. + +func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) { + buf := make([]byte, len(src), 8*BlockSize) + for i := 0; i < len(buf); i += BlockSize { + byteorder.BEPutUint64(buf[i:], ivhi) + byteorder.BEPutUint64(buf[i+8:], ivlo) + ivlo, ivhi = add128(ivlo, ivhi, 1) + encryptBlock(b, buf[i:], buf[i:]) + } + // XOR into buf first, in case src and dst overlap (see above). + subtle.XORBytes(buf, src, buf) + copy(dst, buf) +} + +func add128(lo, hi uint64, x uint64) (uint64, uint64) { + lo, c := bits.Add64(lo, x, 0) + hi, _ = bits.Add64(hi, 0, c) + return lo, hi +} diff --git a/crypto/internal/fips140/aes/ctr_amd64.s b/crypto/internal/fips140/aes/ctr_amd64.s new file mode 100644 index 00000000000..e6710834dd2 --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_amd64.s @@ -0,0 +1,494 @@ +// Code generated by command: go run ctr_amd64_asm.go -out ../../ctr_amd64.s. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +// func ctrBlocks1Asm(nr int, xk *[60]uint32, dst *[16]byte, src *[16]byte, ivlo uint64, ivhi uint64) +// Requires: AES, SSE, SSE2, SSE4.1, SSSE3 +TEXT ·ctrBlocks1Asm(SB), $0-48 + MOVQ nr+0(FP), AX + MOVQ xk+8(FP), CX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVQ ivlo+32(FP), SI + MOVQ ivhi+40(FP), DI + MOVOU bswapMask<>+0(SB), X0 + MOVQ SI, X1 + PINSRQ $0x01, DI, X1 + PSHUFB X0, X1 + MOVUPS (CX), X0 + PXOR X0, X1 + ADDQ $0x10, CX + SUBQ $0x0c, AX + JE enc192 + JB enc128 + MOVUPS (CX), X0 + AESENC X0, X1 + MOVUPS 16(CX), X0 + AESENC X0, X1 + ADDQ $0x20, CX + +enc192: + MOVUPS (CX), X0 + AESENC X0, X1 + MOVUPS 16(CX), X0 + AESENC X0, X1 + ADDQ $0x20, CX + +enc128: + MOVUPS (CX), X0 + AESENC X0, X1 + MOVUPS 16(CX), X0 + AESENC X0, X1 + MOVUPS 32(CX), X0 + AESENC X0, X1 + MOVUPS 48(CX), X0 + AESENC X0, X1 + MOVUPS 64(CX), X0 + AESENC X0, X1 + MOVUPS 80(CX), X0 + AESENC X0, X1 + MOVUPS 96(CX), X0 + AESENC X0, X1 + MOVUPS 112(CX), X0 + AESENC X0, X1 + MOVUPS 128(CX), X0 + AESENC X0, X1 + MOVUPS 144(CX), X0 + AESENCLAST X0, X1 + MOVUPS (BX), X0 + PXOR X1, X0 + MOVUPS X0, (DX) + RET + +DATA bswapMask<>+0(SB)/8, $0x08090a0b0c0d0e0f +DATA bswapMask<>+8(SB)/8, $0x0001020304050607 +GLOBL bswapMask<>(SB), RODATA|NOPTR, $16 + +// func ctrBlocks2Asm(nr int, xk *[60]uint32, dst *[32]byte, src *[32]byte, ivlo uint64, ivhi uint64) +// Requires: AES, SSE, SSE2, SSE4.1, SSSE3 +TEXT ·ctrBlocks2Asm(SB), $0-48 + MOVQ nr+0(FP), AX + MOVQ xk+8(FP), CX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVQ ivlo+32(FP), SI + MOVQ ivhi+40(FP), DI + MOVOU bswapMask<>+0(SB), X0 + MOVQ SI, X1 + PINSRQ $0x01, DI, X1 + PSHUFB X0, X1 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X2 + PINSRQ $0x01, DI, X2 + PSHUFB X0, X2 + MOVUPS (CX), X0 + PXOR X0, X1 + PXOR X0, X2 + ADDQ $0x10, CX + SUBQ $0x0c, AX + JE enc192 + JB enc128 + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + ADDQ $0x20, CX + +enc192: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + ADDQ $0x20, CX + +enc128: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 32(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 48(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 64(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 80(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 96(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 112(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 128(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + MOVUPS 144(CX), X0 + AESENCLAST X0, X1 + AESENCLAST X0, X2 + MOVUPS (BX), X0 + PXOR X1, X0 + MOVUPS X0, (DX) + MOVUPS 16(BX), X0 + PXOR X2, X0 + MOVUPS X0, 16(DX) + RET + +// func ctrBlocks4Asm(nr int, xk *[60]uint32, dst *[64]byte, src *[64]byte, ivlo uint64, ivhi uint64) +// Requires: AES, SSE, SSE2, SSE4.1, SSSE3 +TEXT ·ctrBlocks4Asm(SB), $0-48 + MOVQ nr+0(FP), AX + MOVQ xk+8(FP), CX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVQ ivlo+32(FP), SI + MOVQ ivhi+40(FP), DI + MOVOU bswapMask<>+0(SB), X0 + MOVQ SI, X1 + PINSRQ $0x01, DI, X1 + PSHUFB X0, X1 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X2 + PINSRQ $0x01, DI, X2 + PSHUFB X0, X2 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X3 + PINSRQ $0x01, DI, X3 + PSHUFB X0, X3 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X4 + PINSRQ $0x01, DI, X4 + PSHUFB X0, X4 + MOVUPS (CX), X0 + PXOR X0, X1 + PXOR X0, X2 + PXOR X0, X3 + PXOR X0, X4 + ADDQ $0x10, CX + SUBQ $0x0c, AX + JE enc192 + JB enc128 + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + ADDQ $0x20, CX + +enc192: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + ADDQ $0x20, CX + +enc128: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 32(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 48(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 64(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 80(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 96(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 112(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 128(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + MOVUPS 144(CX), X0 + AESENCLAST X0, X1 + AESENCLAST X0, X2 + AESENCLAST X0, X3 + AESENCLAST X0, X4 + MOVUPS (BX), X0 + PXOR X1, X0 + MOVUPS X0, (DX) + MOVUPS 16(BX), X0 + PXOR X2, X0 + MOVUPS X0, 16(DX) + MOVUPS 32(BX), X0 + PXOR X3, X0 + MOVUPS X0, 32(DX) + MOVUPS 48(BX), X0 + PXOR X4, X0 + MOVUPS X0, 48(DX) + RET + +// func ctrBlocks8Asm(nr int, xk *[60]uint32, dst *[128]byte, src *[128]byte, ivlo uint64, ivhi uint64) +// Requires: AES, SSE, SSE2, SSE4.1, SSSE3 +TEXT ·ctrBlocks8Asm(SB), $0-48 + MOVQ nr+0(FP), AX + MOVQ xk+8(FP), CX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVQ ivlo+32(FP), SI + MOVQ ivhi+40(FP), DI + MOVOU bswapMask<>+0(SB), X0 + MOVQ SI, X1 + PINSRQ $0x01, DI, X1 + PSHUFB X0, X1 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X2 + PINSRQ $0x01, DI, X2 + PSHUFB X0, X2 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X3 + PINSRQ $0x01, DI, X3 + PSHUFB X0, X3 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X4 + PINSRQ $0x01, DI, X4 + PSHUFB X0, X4 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X5 + PINSRQ $0x01, DI, X5 + PSHUFB X0, X5 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X6 + PINSRQ $0x01, DI, X6 + PSHUFB X0, X6 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X7 + PINSRQ $0x01, DI, X7 + PSHUFB X0, X7 + ADDQ $0x01, SI + ADCQ $0x00, DI + MOVQ SI, X8 + PINSRQ $0x01, DI, X8 + PSHUFB X0, X8 + MOVUPS (CX), X0 + PXOR X0, X1 + PXOR X0, X2 + PXOR X0, X3 + PXOR X0, X4 + PXOR X0, X5 + PXOR X0, X6 + PXOR X0, X7 + PXOR X0, X8 + ADDQ $0x10, CX + SUBQ $0x0c, AX + JE enc192 + JB enc128 + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + ADDQ $0x20, CX + +enc192: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + ADDQ $0x20, CX + +enc128: + MOVUPS (CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 16(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 32(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 48(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 64(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 80(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 96(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 112(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 128(CX), X0 + AESENC X0, X1 + AESENC X0, X2 + AESENC X0, X3 + AESENC X0, X4 + AESENC X0, X5 + AESENC X0, X6 + AESENC X0, X7 + AESENC X0, X8 + MOVUPS 144(CX), X0 + AESENCLAST X0, X1 + AESENCLAST X0, X2 + AESENCLAST X0, X3 + AESENCLAST X0, X4 + AESENCLAST X0, X5 + AESENCLAST X0, X6 + AESENCLAST X0, X7 + AESENCLAST X0, X8 + MOVUPS (BX), X0 + PXOR X1, X0 + MOVUPS X0, (DX) + MOVUPS 16(BX), X0 + PXOR X2, X0 + MOVUPS X0, 16(DX) + MOVUPS 32(BX), X0 + PXOR X3, X0 + MOVUPS X0, 32(DX) + MOVUPS 48(BX), X0 + PXOR X4, X0 + MOVUPS X0, 48(DX) + MOVUPS 64(BX), X0 + PXOR X5, X0 + MOVUPS X0, 64(DX) + MOVUPS 80(BX), X0 + PXOR X6, X0 + MOVUPS X0, 80(DX) + MOVUPS 96(BX), X0 + PXOR X7, X0 + MOVUPS X0, 96(DX) + MOVUPS 112(BX), X0 + PXOR X8, X0 + MOVUPS X0, 112(DX) + RET diff --git a/crypto/internal/fips140/aes/ctr_arm64.s b/crypto/internal/fips140/aes/ctr_arm64.s new file mode 100644 index 00000000000..fc4ab4eaada --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_arm64.s @@ -0,0 +1,729 @@ +// Code generated by ctr_arm64_gen.go. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +#define NR R9 +#define XK R10 +#define DST R11 +#define SRC R12 +#define IV_LOW_LE R16 +#define IV_HIGH_LE R17 +#define IV_LOW_BE R19 +#define IV_HIGH_BE R20 + +// V0.B16 - V7.B16 are for blocks (<=8). See BLOCK_OFFSET. +// V8.B16 - V22.B16 are for <=15 round keys (<=15). See ROUND_KEY_OFFSET. +// V23.B16 - V30.B16 are for destinations (<=8). See DST_OFFSET. + +// func ctrBlocks1Asm(nr int, xk *[60]uint32, dst *[1*16]byte, src *[1*16]byte, ivlo uint64, ivhi uint64) +TEXT ·ctrBlocks1Asm(SB), NOSPLIT, $0 + MOVD nr+0(FP), NR + MOVD xk+8(FP), XK + MOVD dst+16(FP), DST + MOVD src+24(FP), SRC + MOVD ivlo+32(FP), IV_LOW_LE + MOVD ivhi+40(FP), IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V0.D[1] + VMOV IV_HIGH_BE, V0.D[0] + + CMP $12, NR + BLT Lenc128 + BEQ Lenc192 + +Lenc256: + VLD1.P 32(XK), [V8.B16, V9.B16] + + AESE V8.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V9.B16, V0.B16 + AESMC V0.B16, V0.B16 + +Lenc192: + VLD1.P 32(XK), [V10.B16, V11.B16] + + AESE V10.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V11.B16, V0.B16 + AESMC V0.B16, V0.B16 + +Lenc128: + VLD1.P 64(XK), [V12.B16, V13.B16, V14.B16, V15.B16] + VLD1.P 64(XK), [V16.B16, V17.B16, V18.B16, V19.B16] + VLD1.P 48(XK), [V20.B16, V21.B16, V22.B16] + + AESE V12.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V13.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V14.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V15.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V16.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V17.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V18.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V19.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V20.B16, V0.B16 + AESMC V0.B16, V0.B16 + + AESE V21.B16, V0.B16 + + VEOR V0.B16, V22.B16, V0.B16 + + VLD1.P 16(SRC), [V23.B16] + VEOR V23.B16, V0.B16, V23.B16 + VST1.P [V23.B16], 16(DST) + + RET + +// func ctrBlocks2Asm(nr int, xk *[60]uint32, dst *[2*16]byte, src *[2*16]byte, ivlo uint64, ivhi uint64) +TEXT ·ctrBlocks2Asm(SB), NOSPLIT, $0 + MOVD nr+0(FP), NR + MOVD xk+8(FP), XK + MOVD dst+16(FP), DST + MOVD src+24(FP), SRC + MOVD ivlo+32(FP), IV_LOW_LE + MOVD ivhi+40(FP), IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V0.D[1] + VMOV IV_HIGH_BE, V0.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V1.D[1] + VMOV IV_HIGH_BE, V1.D[0] + + CMP $12, NR + BLT Lenc128 + BEQ Lenc192 + +Lenc256: + VLD1.P 32(XK), [V8.B16, V9.B16] + + AESE V8.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V8.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V9.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V9.B16, V1.B16 + AESMC V1.B16, V1.B16 + +Lenc192: + VLD1.P 32(XK), [V10.B16, V11.B16] + + AESE V10.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V10.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V11.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V11.B16, V1.B16 + AESMC V1.B16, V1.B16 + +Lenc128: + VLD1.P 64(XK), [V12.B16, V13.B16, V14.B16, V15.B16] + VLD1.P 64(XK), [V16.B16, V17.B16, V18.B16, V19.B16] + VLD1.P 48(XK), [V20.B16, V21.B16, V22.B16] + + AESE V12.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V12.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V13.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V13.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V14.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V14.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V15.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V15.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V16.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V16.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V17.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V17.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V18.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V18.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V19.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V19.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V20.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V20.B16, V1.B16 + AESMC V1.B16, V1.B16 + + AESE V21.B16, V0.B16 + AESE V21.B16, V1.B16 + + VEOR V0.B16, V22.B16, V0.B16 + VEOR V1.B16, V22.B16, V1.B16 + + VLD1.P 32(SRC), [V23.B16, V24.B16] + VEOR V23.B16, V0.B16, V23.B16 + VEOR V24.B16, V1.B16, V24.B16 + VST1.P [V23.B16, V24.B16], 32(DST) + + RET + +// func ctrBlocks4Asm(nr int, xk *[60]uint32, dst *[4*16]byte, src *[4*16]byte, ivlo uint64, ivhi uint64) +TEXT ·ctrBlocks4Asm(SB), NOSPLIT, $0 + MOVD nr+0(FP), NR + MOVD xk+8(FP), XK + MOVD dst+16(FP), DST + MOVD src+24(FP), SRC + MOVD ivlo+32(FP), IV_LOW_LE + MOVD ivhi+40(FP), IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V0.D[1] + VMOV IV_HIGH_BE, V0.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V1.D[1] + VMOV IV_HIGH_BE, V1.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V2.D[1] + VMOV IV_HIGH_BE, V2.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V3.D[1] + VMOV IV_HIGH_BE, V3.D[0] + + CMP $12, NR + BLT Lenc128 + BEQ Lenc192 + +Lenc256: + VLD1.P 32(XK), [V8.B16, V9.B16] + + AESE V8.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V8.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V8.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V8.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V9.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V9.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V9.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V9.B16, V3.B16 + AESMC V3.B16, V3.B16 + +Lenc192: + VLD1.P 32(XK), [V10.B16, V11.B16] + + AESE V10.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V10.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V10.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V10.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V11.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V11.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V11.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V11.B16, V3.B16 + AESMC V3.B16, V3.B16 + +Lenc128: + VLD1.P 64(XK), [V12.B16, V13.B16, V14.B16, V15.B16] + VLD1.P 64(XK), [V16.B16, V17.B16, V18.B16, V19.B16] + VLD1.P 48(XK), [V20.B16, V21.B16, V22.B16] + + AESE V12.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V12.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V12.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V12.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V13.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V13.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V13.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V13.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V14.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V14.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V14.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V14.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V15.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V15.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V15.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V15.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V16.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V16.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V16.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V16.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V17.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V17.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V17.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V17.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V18.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V18.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V18.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V18.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V19.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V19.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V19.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V19.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V20.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V20.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V20.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V20.B16, V3.B16 + AESMC V3.B16, V3.B16 + + AESE V21.B16, V0.B16 + AESE V21.B16, V1.B16 + AESE V21.B16, V2.B16 + AESE V21.B16, V3.B16 + + VEOR V0.B16, V22.B16, V0.B16 + VEOR V1.B16, V22.B16, V1.B16 + VEOR V2.B16, V22.B16, V2.B16 + VEOR V3.B16, V22.B16, V3.B16 + + VLD1.P 64(SRC), [V23.B16, V24.B16, V25.B16, V26.B16] + VEOR V23.B16, V0.B16, V23.B16 + VEOR V24.B16, V1.B16, V24.B16 + VEOR V25.B16, V2.B16, V25.B16 + VEOR V26.B16, V3.B16, V26.B16 + VST1.P [V23.B16, V24.B16, V25.B16, V26.B16], 64(DST) + + RET + +// func ctrBlocks8Asm(nr int, xk *[60]uint32, dst *[8*16]byte, src *[8*16]byte, ivlo uint64, ivhi uint64) +TEXT ·ctrBlocks8Asm(SB), NOSPLIT, $0 + MOVD nr+0(FP), NR + MOVD xk+8(FP), XK + MOVD dst+16(FP), DST + MOVD src+24(FP), SRC + MOVD ivlo+32(FP), IV_LOW_LE + MOVD ivhi+40(FP), IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V0.D[1] + VMOV IV_HIGH_BE, V0.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V1.D[1] + VMOV IV_HIGH_BE, V1.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V2.D[1] + VMOV IV_HIGH_BE, V2.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V3.D[1] + VMOV IV_HIGH_BE, V3.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V4.D[1] + VMOV IV_HIGH_BE, V4.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V5.D[1] + VMOV IV_HIGH_BE, V5.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V6.D[1] + VMOV IV_HIGH_BE, V6.D[0] + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + VMOV IV_LOW_BE, V7.D[1] + VMOV IV_HIGH_BE, V7.D[0] + + CMP $12, NR + BLT Lenc128 + BEQ Lenc192 + +Lenc256: + VLD1.P 32(XK), [V8.B16, V9.B16] + + AESE V8.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V8.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V8.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V8.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V8.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V8.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V8.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V8.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V9.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V9.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V9.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V9.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V9.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V9.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V9.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V9.B16, V7.B16 + AESMC V7.B16, V7.B16 + +Lenc192: + VLD1.P 32(XK), [V10.B16, V11.B16] + + AESE V10.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V10.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V10.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V10.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V10.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V10.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V10.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V10.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V11.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V11.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V11.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V11.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V11.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V11.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V11.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V11.B16, V7.B16 + AESMC V7.B16, V7.B16 + +Lenc128: + VLD1.P 64(XK), [V12.B16, V13.B16, V14.B16, V15.B16] + VLD1.P 64(XK), [V16.B16, V17.B16, V18.B16, V19.B16] + VLD1.P 48(XK), [V20.B16, V21.B16, V22.B16] + + AESE V12.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V12.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V12.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V12.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V12.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V12.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V12.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V12.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V13.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V13.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V13.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V13.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V13.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V13.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V13.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V13.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V14.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V14.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V14.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V14.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V14.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V14.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V14.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V14.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V15.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V15.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V15.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V15.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V15.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V15.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V15.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V15.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V16.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V16.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V16.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V16.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V16.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V16.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V16.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V16.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V17.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V17.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V17.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V17.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V17.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V17.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V17.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V17.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V18.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V18.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V18.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V18.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V18.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V18.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V18.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V18.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V19.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V19.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V19.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V19.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V19.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V19.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V19.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V19.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V20.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V20.B16, V1.B16 + AESMC V1.B16, V1.B16 + AESE V20.B16, V2.B16 + AESMC V2.B16, V2.B16 + AESE V20.B16, V3.B16 + AESMC V3.B16, V3.B16 + AESE V20.B16, V4.B16 + AESMC V4.B16, V4.B16 + AESE V20.B16, V5.B16 + AESMC V5.B16, V5.B16 + AESE V20.B16, V6.B16 + AESMC V6.B16, V6.B16 + AESE V20.B16, V7.B16 + AESMC V7.B16, V7.B16 + + AESE V21.B16, V0.B16 + AESE V21.B16, V1.B16 + AESE V21.B16, V2.B16 + AESE V21.B16, V3.B16 + AESE V21.B16, V4.B16 + AESE V21.B16, V5.B16 + AESE V21.B16, V6.B16 + AESE V21.B16, V7.B16 + + VEOR V0.B16, V22.B16, V0.B16 + VEOR V1.B16, V22.B16, V1.B16 + VEOR V2.B16, V22.B16, V2.B16 + VEOR V3.B16, V22.B16, V3.B16 + VEOR V4.B16, V22.B16, V4.B16 + VEOR V5.B16, V22.B16, V5.B16 + VEOR V6.B16, V22.B16, V6.B16 + VEOR V7.B16, V22.B16, V7.B16 + + VLD1.P 64(SRC), [V23.B16, V24.B16, V25.B16, V26.B16] + VLD1.P 64(SRC), [V27.B16, V28.B16, V29.B16, V30.B16] + VEOR V23.B16, V0.B16, V23.B16 + VEOR V24.B16, V1.B16, V24.B16 + VEOR V25.B16, V2.B16, V25.B16 + VEOR V26.B16, V3.B16, V26.B16 + VEOR V27.B16, V4.B16, V27.B16 + VEOR V28.B16, V5.B16, V28.B16 + VEOR V29.B16, V6.B16, V29.B16 + VEOR V30.B16, V7.B16, V30.B16 + VST1.P [V23.B16, V24.B16, V25.B16, V26.B16], 64(DST) + VST1.P [V27.B16, V28.B16, V29.B16, V30.B16], 64(DST) + + RET + diff --git a/crypto/internal/fips140/aes/ctr_arm64_gen.go b/crypto/internal/fips140/aes/ctr_arm64_gen.go new file mode 100644 index 00000000000..1c032083c35 --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_arm64_gen.go @@ -0,0 +1,213 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +// Generate Go assembly for XORing CTR output to n blocks at once with one key. +package main + +import ( + "fmt" + "os" + "strings" + "text/template" +) + +// First registers in their groups. +const ( + blockOffset = 0 + roundKeyOffset = 8 + dstOffset = 23 +) + +var tmplArm64Str = ` +// Code generated by ctr_arm64_gen.go. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +#define NR R9 +#define XK R10 +#define DST R11 +#define SRC R12 +#define IV_LOW_LE R16 +#define IV_HIGH_LE R17 +#define IV_LOW_BE R19 +#define IV_HIGH_BE R20 + +// V0.B16 - V7.B16 are for blocks (<=8). See BLOCK_OFFSET. +// V8.B16 - V22.B16 are for <=15 round keys (<=15). See ROUND_KEY_OFFSET. +// V23.B16 - V30.B16 are for destinations (<=8). See DST_OFFSET. + +{{define "load_keys"}} + {{- range regs_batches (round_key_reg $.FirstKey) $.NKeys }} + VLD1.P {{ .Size }}(XK), [{{ .Regs }}] + {{- end }} +{{ end }} + +{{define "enc"}} + {{ range $i := xrange $.N -}} + AESE V{{ round_key_reg $.Key}}.B16, V{{ block_reg $i }}.B16 + {{- if $.WithMc }} + AESMC V{{ block_reg $i }}.B16, V{{ block_reg $i }}.B16 + {{- end }} + {{ end }} +{{ end }} + +{{ range $N := $.Sizes }} +// func ctrBlocks{{$N}}Asm(nr int, xk *[60]uint32, dst *[{{$N}}*16]byte, src *[{{$N}}*16]byte, ivlo uint64, ivhi uint64) +TEXT ·ctrBlocks{{ $N }}Asm(SB),NOSPLIT,$0 + MOVD nr+0(FP), NR + MOVD xk+8(FP), XK + MOVD dst+16(FP), DST + MOVD src+24(FP), SRC + MOVD ivlo+32(FP), IV_LOW_LE + MOVD ivhi+40(FP), IV_HIGH_LE + + {{/* Prepare plain from IV and blockIndex. */}} + + {{/* Copy to plaintext registers. */}} + {{ range $i := xrange $N }} + REV IV_LOW_LE, IV_LOW_BE + REV IV_HIGH_LE, IV_HIGH_BE + {{- /* https://developer.arm.com/documentation/dui0801/g/A64-SIMD-Vector-Instructions/MOV--vector--from-general- */}} + VMOV IV_LOW_BE, V{{ block_reg $i }}.D[1] + VMOV IV_HIGH_BE, V{{ block_reg $i }}.D[0] + {{- if ne (add $i 1) $N }} + ADDS $1, IV_LOW_LE + ADC $0, IV_HIGH_LE + {{ end }} + {{ end }} + + {{/* Num rounds branching. */}} + CMP $12, NR + BLT Lenc128 + BEQ Lenc192 + + {{/* 2 extra rounds for 256-bit keys. */}} + Lenc256: + {{- template "load_keys" (load_keys_args 0 2) }} + {{- template "enc" (enc_args 0 $N true) }} + {{- template "enc" (enc_args 1 $N true) }} + + {{/* 2 extra rounds for 192-bit keys. */}} + Lenc192: + {{- template "load_keys" (load_keys_args 2 2) }} + {{- template "enc" (enc_args 2 $N true) }} + {{- template "enc" (enc_args 3 $N true) }} + + {{/* 10 rounds for 128-bit (with special handling for final). */}} + Lenc128: + {{- template "load_keys" (load_keys_args 4 11) }} + {{- range $r := xrange 9 }} + {{- template "enc" (enc_args (add $r 4) $N true) }} + {{ end }} + {{ template "enc" (enc_args 13 $N false) }} + + {{/* We need to XOR blocks with the last round key (key 14, register V22). */}} + {{ range $i := xrange $N }} + VEOR V{{ block_reg $i }}.B16, V{{ round_key_reg 14 }}.B16, V{{ block_reg $i }}.B16 + {{- end }} + + {{/* XOR results to destination. */}} + {{- range regs_batches $.DstOffset $N }} + VLD1.P {{ .Size }}(SRC), [{{ .Regs }}] + {{- end }} + {{- range $i := xrange $N }} + VEOR V{{ add $.DstOffset $i }}.B16, V{{ block_reg $i }}.B16, V{{ add $.DstOffset $i }}.B16 + {{- end }} + {{- range regs_batches $.DstOffset $N }} + VST1.P [{{ .Regs }}], {{ .Size }}(DST) + {{- end }} + + RET +{{ end }} +` + +func main() { + type Params struct { + DstOffset int + Sizes []int + } + + params := Params{ + DstOffset: dstOffset, + Sizes: []int{1, 2, 4, 8}, + } + + type RegsBatch struct { + Size int + Regs string // Comma-separated list of registers. + } + + type LoadKeysArgs struct { + FirstKey int + NKeys int + } + + type EncArgs struct { + Key int + N int + WithMc bool + } + + funcs := template.FuncMap{ + "add": func(a, b int) int { + return a + b + }, + "xrange": func(n int) []int { + result := make([]int, n) + for i := 0; i < n; i++ { + result[i] = i + } + return result + }, + "block_reg": func(block int) int { + return blockOffset + block + }, + "round_key_reg": func(key int) int { + return roundKeyOffset + key + }, + "regs_batches": func(firstReg, nregs int) []RegsBatch { + result := make([]RegsBatch, 0) + for nregs != 0 { + batch := 4 + if nregs < batch { + batch = nregs + } + regsList := make([]string, 0, batch) + for j := firstReg; j < firstReg+batch; j++ { + regsList = append(regsList, fmt.Sprintf("V%d.B16", j)) + } + result = append(result, RegsBatch{ + Size: 16 * batch, + Regs: strings.Join(regsList, ", "), + }) + nregs -= batch + firstReg += batch + } + return result + }, + "enc_args": func(key, n int, withMc bool) EncArgs { + return EncArgs{ + Key: key, + N: n, + WithMc: withMc, + } + }, + "load_keys_args": func(firstKey, nkeys int) LoadKeysArgs { + return LoadKeysArgs{ + FirstKey: firstKey, + NKeys: nkeys, + } + }, + } + + var tmpl = template.Must(template.New("ctr_arm64").Funcs(funcs).Parse(tmplArm64Str)) + + if err := tmpl.Execute(os.Stdout, params); err != nil { + panic(err) + } +} diff --git a/crypto/internal/fips140/aes/ctr_asm.go b/crypto/internal/fips140/aes/ctr_asm.go new file mode 100644 index 00000000000..463e232c45c --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_asm.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (amd64 || arm64 || ppc64 || ppc64le) && !purego + +package aes + +//go:generate sh -c "go run ./ctr_arm64_gen.go | asmfmt > ctr_arm64.s" + +//go:noescape +func ctrBlocks1Asm(nr int, xk *[60]uint32, dst, src *[BlockSize]byte, ivlo, ivhi uint64) + +//go:noescape +func ctrBlocks2Asm(nr int, xk *[60]uint32, dst, src *[2 * BlockSize]byte, ivlo, ivhi uint64) + +//go:noescape +func ctrBlocks4Asm(nr int, xk *[60]uint32, dst, src *[4 * BlockSize]byte, ivlo, ivhi uint64) + +//go:noescape +func ctrBlocks8Asm(nr int, xk *[60]uint32, dst, src *[8 * BlockSize]byte, ivlo, ivhi uint64) + +func ctrBlocks1(b *Block, dst, src *[BlockSize]byte, ivlo, ivhi uint64) { + if !supportsAES { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) + } else { + ctrBlocks1Asm(b.rounds, &b.enc, dst, src, ivlo, ivhi) + } +} + +func ctrBlocks2(b *Block, dst, src *[2 * BlockSize]byte, ivlo, ivhi uint64) { + if !supportsAES { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) + } else { + ctrBlocks2Asm(b.rounds, &b.enc, dst, src, ivlo, ivhi) + } +} + +func ctrBlocks4(b *Block, dst, src *[4 * BlockSize]byte, ivlo, ivhi uint64) { + if !supportsAES { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) + } else { + ctrBlocks4Asm(b.rounds, &b.enc, dst, src, ivlo, ivhi) + } +} + +func ctrBlocks8(b *Block, dst, src *[8 * BlockSize]byte, ivlo, ivhi uint64) { + if !supportsAES { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) + } else { + ctrBlocks8Asm(b.rounds, &b.enc, dst, src, ivlo, ivhi) + } +} diff --git a/crypto/internal/fips140/aes/ctr_noasm.go b/crypto/internal/fips140/aes/ctr_noasm.go new file mode 100644 index 00000000000..a170606a6db --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_noasm.go @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !arm64 && !s390x && !ppc64 && !ppc64le) || purego + +package aes + +func ctrBlocks1(b *Block, dst, src *[BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks2(b *Block, dst, src *[2 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks4(b *Block, dst, src *[4 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks8(b *Block, dst, src *[8 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocks(b, dst[:], src[:], ivlo, ivhi) +} diff --git a/crypto/internal/fips140/aes/ctr_s390x.go b/crypto/internal/fips140/aes/ctr_s390x.go new file mode 100644 index 00000000000..d8865d6e2e1 --- /dev/null +++ b/crypto/internal/fips140/aes/ctr_s390x.go @@ -0,0 +1,49 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package aes + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +func ctrBlocks1(b *Block, dst, src *[BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocksS390x(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks2(b *Block, dst, src *[2 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocksS390x(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks4(b *Block, dst, src *[4 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocksS390x(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocks8(b *Block, dst, src *[8 * BlockSize]byte, ivlo, ivhi uint64) { + ctrBlocksS390x(b, dst[:], src[:], ivlo, ivhi) +} + +func ctrBlocksS390x(b *Block, dst, src []byte, ivlo, ivhi uint64) { + if b.fallback != nil { + ctrBlocks(b, dst, src, ivlo, ivhi) + return + } + + buf := make([]byte, len(src), 8*BlockSize) + for i := 0; i < len(buf); i += BlockSize { + byteorder.BEPutUint64(buf[i:], ivhi) + byteorder.BEPutUint64(buf[i+8:], ivlo) + ivlo, ivhi = add128(ivlo, ivhi, 1) + } + + // Encrypt the buffer using AES in ECB mode. + cryptBlocks(b.function, &b.key[0], &buf[0], &buf[0], len(buf)) + + // XOR into buf first, in case src and dst overlap (see ctrBlocks). + subtle.XORBytes(buf, src, buf) + copy(dst, buf) +} diff --git a/crypto/aes/_asm/gcm/gcm_amd64_asm.go b/crypto/internal/fips140/aes/gcm/_asm/gcm/gcm_amd64_asm.go similarity index 99% rename from crypto/aes/_asm/gcm/gcm_amd64_asm.go rename to crypto/internal/fips140/aes/gcm/_asm/gcm/gcm_amd64_asm.go index 60a82674c33..ed5f14b9386 100644 --- a/crypto/aes/_asm/gcm/gcm_amd64_asm.go +++ b/crypto/internal/fips140/aes/gcm/_asm/gcm/gcm_amd64_asm.go @@ -18,7 +18,7 @@ import ( . "github.com/mmcloughlin/avo/reg" ) -//go:generate go run . -out ../../gcm_amd64.s -pkg aes +//go:generate go run . -out ../../gcm_amd64.s var ( B0 VecPhysical = X0 @@ -42,7 +42,7 @@ var ( ) func main() { - Package("github.com/runZeroInc/excrypto/crypto/aes") + Package("crypto/aes") ConstraintExpr("!purego") gcmAesFinish() diff --git a/crypto/internal/fips140/aes/gcm/_asm/gcm/go.mod b/crypto/internal/fips140/aes/gcm/_asm/gcm/go.mod new file mode 100644 index 00000000000..3fd2094068e --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/_asm/gcm/go.mod @@ -0,0 +1,11 @@ +module crypto/aes/_asm/gcm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/aes/gcm/_asm/gcm/go.sum b/crypto/internal/fips140/aes/gcm/_asm/gcm/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/_asm/gcm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/internal/fips140/aes/gcm/cast.go b/crypto/internal/fips140/aes/gcm/cast.go new file mode 100644 index 00000000000..2f32161875d --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/cast.go @@ -0,0 +1,45 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "errors" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" +) + +func init() { + // Counter KDF covers CMAC per IG 10.3.B, and CMAC covers GCM per IG 10.3.A + // Resolution 1.d(i). AES decryption is covered by the CBC CAST in package + // crypto/internal/fips140/aes. + fips140.CAST("CounterKDF", func() error { + key := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + context := [12]byte{ + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, + } + want := [32]byte{ + 0xe6, 0x86, 0x96, 0x97, 0x08, 0xfc, 0x90, 0x30, + 0x36, 0x1c, 0x65, 0x94, 0xb2, 0x62, 0xa5, 0xf7, + 0xcb, 0x9d, 0x93, 0x94, 0xda, 0xf1, 0x94, 0x09, + 0x6a, 0x27, 0x5e, 0x85, 0x22, 0x5e, 0x7a, 0xee, + } + b, err := aes.New(key) + if err != nil { + return err + } + got := NewCounterKDF(b).DeriveKey(0xFF, context) + if got != want { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/aes/gcm/cmac.go b/crypto/internal/fips140/aes/gcm/cmac.go new file mode 100644 index 00000000000..c55bbfe7798 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/cmac.go @@ -0,0 +1,77 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" +) + +// CMAC implements the CMAC mode from NIST SP 800-38B. +// +// It is optimized for use in Counter KDF (SP 800-108r1) and XAES-256-GCM +// (https://c2sp.org/XAES-256-GCM), rather than for exposing it to applications +// as a stand-alone MAC. +type CMAC struct { + b aes.Block + k1 [aes.BlockSize]byte + k2 [aes.BlockSize]byte +} + +func NewCMAC(b *aes.Block) *CMAC { + c := &CMAC{b: *b} + c.deriveSubkeys() + return c +} + +func (c *CMAC) deriveSubkeys() { + aes.EncryptBlockInternal(&c.b, c.k1[:], c.k1[:]) + msb := shiftLeft(&c.k1) + c.k1[len(c.k1)-1] ^= msb * 0b10000111 + + c.k2 = c.k1 + msb = shiftLeft(&c.k2) + c.k2[len(c.k2)-1] ^= msb * 0b10000111 +} + +func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { + fips140.RecordApproved() + _ = c.b // Hoist the nil check out of the loop. + var x [aes.BlockSize]byte + if len(m) == 0 { + // Special-cased as a single empty partial final block. + x = c.k2 + x[len(m)] ^= 0b10000000 + aes.EncryptBlockInternal(&c.b, x[:], x[:]) + return x + } + for len(m) >= aes.BlockSize { + subtle.XORBytes(x[:], m[:aes.BlockSize], x[:]) + if len(m) == aes.BlockSize { + // Final complete block. + subtle.XORBytes(x[:], c.k1[:], x[:]) + } + aes.EncryptBlockInternal(&c.b, x[:], x[:]) + m = m[aes.BlockSize:] + } + if len(m) > 0 { + // Final incomplete block. + subtle.XORBytes(x[:], m, x[:]) + subtle.XORBytes(x[:], c.k2[:], x[:]) + x[len(m)] ^= 0b10000000 + aes.EncryptBlockInternal(&c.b, x[:], x[:]) + } + return x +} + +// shiftLeft sets x to x << 1, and returns MSB₁(x). +func shiftLeft(x *[aes.BlockSize]byte) byte { + var msb byte + for i := len(x) - 1; i >= 0; i-- { + msb, x[i] = x[i]>>7, x[i]<<1|msb + } + return msb +} diff --git a/crypto/internal/fips140/aes/gcm/ctrkdf.go b/crypto/internal/fips140/aes/gcm/ctrkdf.go new file mode 100644 index 00000000000..4b9491ceefe --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/ctrkdf.go @@ -0,0 +1,49 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" +) + +// CounterKDF implements a KDF in Counter Mode instantiated with CMAC-AES, +// according to NIST SP 800-108 Revision 1 Update 1, Section 4.1. +// +// It produces a 256-bit output, and accepts a 8-bit Label and a 96-bit Context. +// It uses a counter of 16 bits placed before the fixed data. The fixed data is +// the sequence Label || 0x00 || Context. The L field is omitted, since the +// output key length is fixed. +// +// It's optimized for use in XAES-256-GCM (https://c2sp.org/XAES-256-GCM), +// rather than for exposing it to applications as a stand-alone KDF. +type CounterKDF struct { + mac CMAC +} + +// NewCounterKDF creates a new CounterKDF with the given key. +func NewCounterKDF(b *aes.Block) *CounterKDF { + return &CounterKDF{mac: *NewCMAC(b)} +} + +// DeriveKey derives a key from the given label and context. +func (kdf *CounterKDF) DeriveKey(label byte, context [12]byte) [32]byte { + fips140.RecordApproved() + var output [32]byte + + var input [aes.BlockSize]byte + input[2] = label + copy(input[4:], context[:]) + + input[1] = 0x01 // i = 1 + K1 := kdf.mac.MAC(input[:]) + + input[1] = 0x02 // i = 2 + K2 := kdf.mac.MAC(input[:]) + + copy(output[:], K1[:]) + copy(output[aes.BlockSize:], K2[:]) + return output +} diff --git a/crypto/internal/fips140/aes/gcm/gcm.go b/crypto/internal/fips140/aes/gcm/gcm.go new file mode 100644 index 00000000000..9d11ee6975f --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm.go @@ -0,0 +1,144 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" +) + +// GCM represents a Galois Counter Mode with a specific key. +type GCM struct { + cipher aes.Block + nonceSize int + tagSize int + gcmPlatformData +} + +func New(cipher *aes.Block, nonceSize, tagSize int) (*GCM, error) { + // This function is outlined to let the allocation happen on the parent stack. + return newGCM(&GCM{}, cipher, nonceSize, tagSize) +} + +// newGCM is marked go:noinline to avoid it inlining into New, and making New +// too complex to inline itself. +// +//go:noinline +func newGCM(g *GCM, cipher *aes.Block, nonceSize, tagSize int) (*GCM, error) { + if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { + return nil, errors.New("cipher: incorrect tag size given to GCM") + } + if nonceSize <= 0 { + return nil, errors.New("cipher: the nonce can't have zero length") + } + if cipher.BlockSize() != gcmBlockSize { + return nil, errors.New("cipher: NewGCM requires 128-bit block cipher") + } + g.cipher = *cipher + g.nonceSize = nonceSize + g.tagSize = tagSize + initGCM(g) + return g, nil +} + +const ( + gcmBlockSize = 16 + gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. + gcmStandardNonceSize = 12 +) + +func (g *GCM) NonceSize() int { + return g.nonceSize +} + +func (g *GCM) Overhead() int { + return g.tagSize +} + +func (g *GCM) Seal(dst, nonce, plaintext, data []byte) []byte { + fips140.RecordNonApproved() + return g.sealAfterIndicator(dst, nonce, plaintext, data) +} + +func (g *GCM) sealAfterIndicator(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if g.nonceSize == 0 { + panic("crypto/cipher: incorrect GCM nonce size") + } + if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize { + panic("crypto/cipher: message too large for GCM") + } + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if alias.InexactOverlap(out, plaintext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, data) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") + } + + seal(out, g, nonce, plaintext, data) + return ret +} + +var errOpen = errors.New("cipher: message authentication failed") + +func (g *GCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an + // implementation leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > uint64((1<<32)-2)*gcmBlockSize+uint64(g.tagSize) { + return nil, errOpen + } + + ret, out := sliceForAppend(dst, len(ciphertext)-g.tagSize) + if alias.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, data) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") + } + + fips140.RecordApproved() + if err := open(out, g, nonce, ciphertext, data); err != nil { + // We sometimes decrypt and authenticate concurrently, so we overwrite + // dst in the event of a tag mismatch. To be consistent across platforms + // and to avoid releasing unauthenticated plaintext, we clear the buffer + // in the event of an error. + clear(out) + return nil, err + } + return ret, nil +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} diff --git a/crypto/aes/gcm_amd64.s b/crypto/internal/fips140/aes/gcm/gcm_amd64.s similarity index 100% rename from crypto/aes/gcm_amd64.s rename to crypto/internal/fips140/aes/gcm/gcm_amd64.s diff --git a/crypto/aes/gcm_arm64.s b/crypto/internal/fips140/aes/gcm/gcm_arm64.s similarity index 100% rename from crypto/aes/gcm_arm64.s rename to crypto/internal/fips140/aes/gcm/gcm_arm64.s diff --git a/crypto/internal/fips140/aes/gcm/gcm_asm.go b/crypto/internal/fips140/aes/gcm/gcm_asm.go new file mode 100644 index 00000000000..cd6dc02db33 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_asm.go @@ -0,0 +1,131 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (amd64 || arm64) && !purego + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// The following functions are defined in gcm_*.s. + +//go:noescape +func gcmAesInit(productTable *[256]byte, ks []uint32) + +//go:noescape +func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte) + +//go:noescape +func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) + +//go:noescape +func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) + +//go:noescape +func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64) + +// Keep in sync with crypto/tls.hasAESGCMHardwareSupport. +var supportsAESGCM = cpu.X86HasAES && cpu.X86HasPCLMULQDQ && cpu.X86HasSSE41 && cpu.X86HasSSSE3 || + cpu.ARM64HasAES && cpu.ARM64HasPMULL + +func init() { + if cpu.AMD64 { + impl.Register("gcm", "AES-NI", &supportsAESGCM) + } + if cpu.ARM64 { + impl.Register("gcm", "Armv8.0", &supportsAESGCM) + } +} + +// checkGenericIsExpected is called by the variable-time implementation to make +// sure it is not used when hardware support is available. It shouldn't happen, +// but this way it's more evidently correct. +func checkGenericIsExpected() { + if supportsAESGCM { + panic("gcm: internal error: using generic implementation despite hardware support") + } +} + +type gcmPlatformData struct { + productTable [256]byte +} + +func initGCM(g *GCM) { + if !supportsAESGCM { + return + } + gcmAesInit(&g.productTable, aes.EncryptionKeySchedule(&g.cipher)) +} + +func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + if !supportsAESGCM { + sealGeneric(out, g, nonce, plaintext, data) + return + } + + var counter, tagMask [gcmBlockSize]byte + + if len(nonce) == gcmStandardNonceSize { + // Init counter to nonce||1 + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + // Otherwise counter = GHASH(nonce) + gcmAesData(&g.productTable, nonce, &counter) + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + + var tagOut [gcmTagSize]byte + gcmAesData(&g.productTable, data, &tagOut) + + if len(plaintext) > 0 { + gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, aes.EncryptionKeySchedule(&g.cipher)) + } + gcmAesFinish(&g.productTable, &tagMask, &tagOut, uint64(len(plaintext)), uint64(len(data))) + copy(out[len(plaintext):], tagOut[:]) +} + +func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + if !supportsAESGCM { + return openGeneric(out, g, nonce, ciphertext, data) + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + // See GCM spec, section 7.1. + var counter, tagMask [gcmBlockSize]byte + + if len(nonce) == gcmStandardNonceSize { + // Init counter to nonce||1 + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + // Otherwise counter = GHASH(nonce) + gcmAesData(&g.productTable, nonce, &counter) + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + + var expectedTag [gcmTagSize]byte + gcmAesData(&g.productTable, data, &expectedTag) + + if len(ciphertext) > 0 { + gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, aes.EncryptionKeySchedule(&g.cipher)) + } + gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data))) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + return errOpen + } + return nil +} diff --git a/crypto/internal/fips140/aes/gcm/gcm_generic.go b/crypto/internal/fips140/aes/gcm/gcm_generic.go new file mode 100644 index 00000000000..45ce7d004e4 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_generic.go @@ -0,0 +1,105 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { + var H, counter, tagMask [gcmBlockSize]byte + aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) + deriveCounterGeneric(&H, &counter, nonce) + gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) + + gcmCounterCryptGeneric(&g.cipher, out, plaintext, &counter) + + var tag [gcmTagSize]byte + gcmAuthGeneric(tag[:], &H, &tagMask, out[:len(plaintext)], additionalData) + copy(out[len(plaintext):], tag[:]) +} + +func openGeneric(out []byte, g *GCM, nonce, ciphertext, additionalData []byte) error { + var H, counter, tagMask [gcmBlockSize]byte + aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) + deriveCounterGeneric(&H, &counter, nonce) + gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var expectedTag [gcmTagSize]byte + gcmAuthGeneric(expectedTag[:], &H, &tagMask, ciphertext, additionalData) + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + return errOpen + } + + gcmCounterCryptGeneric(&g.cipher, out, ciphertext, &counter) + + return nil +} + +// deriveCounterGeneric computes the initial GCM counter state from the given nonce. +// See NIST SP 800-38D, section 7.1. This assumes that counter is filled with +// zeros on entry. +func deriveCounterGeneric(H, counter *[gcmBlockSize]byte, nonce []byte) { + // GCM has two modes of operation with respect to the initial counter + // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" + // for nonces of other lengths. For a 96-bit nonce, the nonce, along + // with a four-byte big-endian counter starting at one, is used + // directly as the starting counter. For other nonce sizes, the counter + // is computed by passing it through the GHASH function. + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + lenBlock := make([]byte, 16) + byteorder.BEPutUint64(lenBlock[8:], uint64(len(nonce))*8) + ghash(counter, H, nonce, lenBlock) + } +} + +// gcmCounterCryptGeneric encrypts src using AES in counter mode with 32-bit +// wrapping (which is different from AES-CTR) and places the result into out. +// counter is the initial value and will be updated with the next value. +func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSize]byte) { + var mask [gcmBlockSize]byte + + for len(src) >= gcmBlockSize { + aes.EncryptBlockInternal(b, mask[:], counter[:]) + gcmInc32(counter) + + subtle.XORBytes(out, src, mask[:]) + out = out[gcmBlockSize:] + src = src[gcmBlockSize:] + } + + if len(src) > 0 { + aes.EncryptBlockInternal(b, mask[:], counter[:]) + gcmInc32(counter) + subtle.XORBytes(out, src, mask[:]) + } +} + +// gcmInc32 treats the final four bytes of counterBlock as a big-endian value +// and increments it. +func gcmInc32(counterBlock *[gcmBlockSize]byte) { + ctr := counterBlock[len(counterBlock)-4:] + byteorder.BEPutUint32(ctr, byteorder.BEUint32(ctr)+1) +} + +// gcmAuthGeneric calculates GHASH(additionalData, ciphertext), masks the result +// with tagMask and writes the result to out. +func gcmAuthGeneric(out []byte, H, tagMask *[gcmBlockSize]byte, ciphertext, additionalData []byte) { + checkGenericIsExpected() + lenBlock := make([]byte, 16) + byteorder.BEPutUint64(lenBlock[:8], uint64(len(additionalData))*8) + byteorder.BEPutUint64(lenBlock[8:], uint64(len(ciphertext))*8) + var S [gcmBlockSize]byte + ghash(&S, H, additionalData, ciphertext, lenBlock) + subtle.XORBytes(out, S[:], tagMask[:]) +} diff --git a/crypto/internal/fips140/aes/gcm/gcm_noasm.go b/crypto/internal/fips140/aes/gcm/gcm_noasm.go new file mode 100644 index 00000000000..4ae3831a458 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_noasm.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !s390x && !ppc64 && !ppc64le && !arm64) || purego + +package gcm + +func checkGenericIsExpected() {} + +type gcmPlatformData struct{} + +func initGCM(g *GCM) {} + +func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + sealGeneric(out, g, nonce, plaintext, data) +} + +func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + return openGeneric(out, g, nonce, ciphertext, data) +} diff --git a/crypto/internal/fips140/aes/gcm/gcm_nonces.go b/crypto/internal/fips140/aes/gcm/gcm_nonces.go new file mode 100644 index 00000000000..0d4c41caaae --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_nonces.go @@ -0,0 +1,258 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "math" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// SealWithRandomNonce encrypts plaintext to out, and writes a random nonce to +// nonce. nonce must be 12 bytes, and out must be 16 bytes longer than plaintext. +// out and plaintext may overlap exactly or not at all. additionalData and out +// must not overlap. +// +// This complies with FIPS 140-3 IG C.H Scenario 2. +// +// Note that this is NOT a [cipher.AEAD].Seal method. +func SealWithRandomNonce(g *GCM, nonce, out, plaintext, additionalData []byte) { + if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize { + panic("crypto/cipher: message too large for GCM") + } + if len(nonce) != gcmStandardNonceSize { + panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce") + } + if len(out) != len(plaintext)+gcmTagSize { + panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce") + } + if alias.InexactOverlap(out, plaintext) { + panic("crypto/cipher: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("crypto/cipher: invalid buffer overlap of output and additional data") + } + fips140.RecordApproved() + drbg.Read(nonce) + seal(out, g, nonce, plaintext, additionalData) +} + +// NewGCMWithCounterNonce returns a new AEAD that works like GCM, but enforces +// the construction of deterministic nonces. The nonce must be 96 bits, the +// first 32 bits must be an encoding of the module name, and the last 64 bits +// must be a counter. +// +// This complies with FIPS 140-3 IG C.H Scenario 3. +func NewGCMWithCounterNonce(cipher *aes.Block) (*GCMWithCounterNonce, error) { + g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err + } + return &GCMWithCounterNonce{g: *g}, nil +} + +type GCMWithCounterNonce struct { + g GCM + ready bool + fixedName uint32 + start uint64 + next uint64 +} + +func (g *GCMWithCounterNonce) NonceSize() int { return gcmStandardNonceSize } + +func (g *GCMWithCounterNonce) Overhead() int { return gcmTagSize } + +func (g *GCMWithCounterNonce) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != gcmStandardNonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + if !g.ready { + // The first invocation sets the fixed name encoding and start counter. + g.ready = true + g.start = counter + g.fixedName = byteorder.BEUint32(nonce[:4]) + } + if g.fixedName != byteorder.BEUint32(nonce[:4]) { + panic("crypto/cipher: incorrect module name given to GCMWithCounterNonce") + } + counter -= g.start + + // Ensure the counter is monotonically increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter wrapped") + } + if counter < g.next { + panic("crypto/cipher: counter decreased") + } + g.next = counter + 1 + + fips140.RecordApproved() + return g.g.sealAfterIndicator(dst, nonce, plaintext, data) +} + +func (g *GCMWithCounterNonce) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + fips140.RecordApproved() + return g.g.Open(dst, nonce, ciphertext, data) +} + +// NewGCMForTLS12 returns a new AEAD that works like GCM, but enforces the +// construction of nonces as specified in RFC 5288, Section 3 and RFC 9325, +// Section 7.2.1. +// +// This complies with FIPS 140-3 IG C.H Scenario 1.a. +func NewGCMForTLS12(cipher *aes.Block) (*GCMForTLS12, error) { + g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err + } + return &GCMForTLS12{g: *g}, nil +} + +type GCMForTLS12 struct { + g GCM + next uint64 +} + +func (g *GCMForTLS12) NonceSize() int { return gcmStandardNonceSize } + +func (g *GCMForTLS12) Overhead() int { return gcmTagSize } + +func (g *GCMForTLS12) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != gcmStandardNonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + + // Ensure the counter is monotonically increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter wrapped") + } + if counter < g.next { + panic("crypto/cipher: counter decreased") + } + g.next = counter + 1 + + fips140.RecordApproved() + return g.g.sealAfterIndicator(dst, nonce, plaintext, data) +} + +func (g *GCMForTLS12) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + fips140.RecordApproved() + return g.g.Open(dst, nonce, ciphertext, data) +} + +// NewGCMForTLS13 returns a new AEAD that works like GCM, but enforces the +// construction of nonces as specified in RFC 8446, Section 5.3. +func NewGCMForTLS13(cipher *aes.Block) (*GCMForTLS13, error) { + g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err + } + return &GCMForTLS13{g: *g}, nil +} + +type GCMForTLS13 struct { + g GCM + ready bool + mask uint64 + next uint64 +} + +func (g *GCMForTLS13) NonceSize() int { return gcmStandardNonceSize } + +func (g *GCMForTLS13) Overhead() int { return gcmTagSize } + +func (g *GCMForTLS13) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != gcmStandardNonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + if !g.ready { + // In the first call, the counter is zero, so we learn the XOR mask. + g.ready = true + g.mask = counter + } + counter ^= g.mask + + // Ensure the counter is monotonically increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter wrapped") + } + if counter < g.next { + panic("crypto/cipher: counter decreased") + } + g.next = counter + 1 + + fips140.RecordApproved() + return g.g.sealAfterIndicator(dst, nonce, plaintext, data) +} + +func (g *GCMForTLS13) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + fips140.RecordApproved() + return g.g.Open(dst, nonce, ciphertext, data) +} + +// NewGCMForSSH returns a new AEAD that works like GCM, but enforces the +// construction of nonces as specified in RFC 5647. +// +// This complies with FIPS 140-3 IG C.H Scenario 1.d. +func NewGCMForSSH(cipher *aes.Block) (*GCMForSSH, error) { + g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err + } + return &GCMForSSH{g: *g}, nil +} + +type GCMForSSH struct { + g GCM + ready bool + start uint64 + next uint64 +} + +func (g *GCMForSSH) NonceSize() int { return gcmStandardNonceSize } + +func (g *GCMForSSH) Overhead() int { return gcmTagSize } + +func (g *GCMForSSH) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != gcmStandardNonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + if !g.ready { + // In the first call we learn the start value. + g.ready = true + g.start = counter + } + counter -= g.start + + // Ensure the counter is monotonically increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter wrapped") + } + if counter < g.next { + panic("crypto/cipher: counter decreased") + } + g.next = counter + 1 + + fips140.RecordApproved() + return g.g.sealAfterIndicator(dst, nonce, plaintext, data) +} + +func (g *GCMForSSH) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + fips140.RecordApproved() + return g.g.Open(dst, nonce, ciphertext, data) +} diff --git a/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go b/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go new file mode 100644 index 00000000000..84dc2fb318e --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go @@ -0,0 +1,188 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64le || ppc64) && !purego + +package gcm + +import ( + "runtime" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// This file implements GCM using an optimized GHASH function. + +//go:noescape +func gcmInit(productTable *[256]byte, h []byte) + +//go:noescape +func gcmHash(output []byte, productTable *[256]byte, inp []byte, len int) + +func counterCryptASM(nr int, out, in []byte, counter *[gcmBlockSize]byte, key *uint32) + +// The POWER architecture doesn't have a way to turn off AES-GCM support +// at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG +// knob for that. It's intentionally only checked at init() time, to +// avoid the performance overhead of checking it every time. +var supportsAESGCM = godebug.Value("#ppc64gcm") != "off" + +func init() { + impl.Register("gcm", "POWER8", &supportsAESGCM) +} + +func checkGenericIsExpected() { + if supportsAESGCM { + panic("gcm: internal error: using generic implementation despite hardware support") + } +} + +type gcmPlatformData struct { + productTable [256]byte +} + +func initGCM(g *GCM) { + if !supportsAESGCM { + return + } + + hle := make([]byte, gcmBlockSize) + aes.EncryptBlockInternal(&g.cipher, hle, hle) + + // Reverse the bytes in each 8 byte chunk + // Load little endian, store big endian + var h1, h2 uint64 + if runtime.GOARCH == "ppc64le" { + h1 = byteorder.LEUint64(hle[:8]) + h2 = byteorder.LEUint64(hle[8:]) + } else { + h1 = byteorder.BEUint64(hle[:8]) + h2 = byteorder.BEUint64(hle[8:]) + } + byteorder.BEPutUint64(hle[:8], h1) + byteorder.BEPutUint64(hle[8:], h2) + gcmInit(&g.productTable, hle) +} + +// deriveCounter computes the initial GCM counter state from the given nonce. +func deriveCounter(counter *[gcmBlockSize]byte, nonce []byte, productTable *[256]byte) { + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + var hash [16]byte + paddedGHASH(&hash, nonce, productTable) + lens := gcmLengths(0, uint64(len(nonce))*8) + paddedGHASH(&hash, lens[:], productTable) + copy(counter[:], hash[:]) + } +} + +// counterCrypt encrypts in using AES in counter mode and places the result +// into out. counter is the initial count value and will be updated with the next +// count value. The length of out must be greater than or equal to the length +// of in. +// counterCryptASM implements counterCrypt which then allows the loop to +// be unrolled and optimized. +func counterCrypt(b *aes.Block, out, in []byte, counter *[gcmBlockSize]byte) { + enc := aes.EncryptionKeySchedule(b) + rounds := len(enc)/4 - 1 + counterCryptASM(rounds, out, in, counter, &enc[0]) +} + +// paddedGHASH pads data with zeroes until its length is a multiple of +// 16-bytes. It then calculates a new value for hash using the ghash +// algorithm. +func paddedGHASH(hash *[16]byte, data []byte, productTable *[256]byte) { + if siz := len(data) - (len(data) % gcmBlockSize); siz > 0 { + gcmHash(hash[:], productTable, data[:], siz) + data = data[siz:] + } + if len(data) > 0 { + var s [16]byte + copy(s[:], data) + gcmHash(hash[:], productTable, s[:], len(s)) + } +} + +// auth calculates GHASH(ciphertext, additionalData), masks the result with +// tagMask and writes the result to out. +func auth(out, ciphertext, aad []byte, tagMask *[gcmTagSize]byte, productTable *[256]byte) { + var hash [16]byte + paddedGHASH(&hash, aad, productTable) + paddedGHASH(&hash, ciphertext, productTable) + lens := gcmLengths(uint64(len(aad))*8, uint64(len(ciphertext))*8) + paddedGHASH(&hash, lens[:], productTable) + + copy(out, hash[:]) + for i := range out { + out[i] ^= tagMask[i] + } +} + +func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + if !supportsAESGCM { + sealGeneric(out, g, nonce, plaintext, data) + return + } + + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&counter, nonce, &g.productTable) + + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + gcmInc32(&counter) + + counterCrypt(&g.cipher, out, plaintext, &counter) + auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask, &g.productTable) +} + +func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + if !supportsAESGCM { + return openGeneric(out, g, nonce, ciphertext, data) + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&counter, nonce, &g.productTable) + + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + gcmInc32(&counter) + + var expectedTag [gcmTagSize]byte + auth(expectedTag[:], ciphertext, data, &tagMask, &g.productTable) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + return errOpen + } + + counterCrypt(&g.cipher, out, ciphertext, &counter) + return nil +} + +func gcmLengths(len0, len1 uint64) [16]byte { + return [16]byte{ + byte(len0 >> 56), + byte(len0 >> 48), + byte(len0 >> 40), + byte(len0 >> 32), + byte(len0 >> 24), + byte(len0 >> 16), + byte(len0 >> 8), + byte(len0), + byte(len1 >> 56), + byte(len1 >> 48), + byte(len1 >> 40), + byte(len1 >> 32), + byte(len1 >> 24), + byte(len1 >> 16), + byte(len1 >> 8), + byte(len1), + } +} diff --git a/crypto/aes/gcm_ppc64x.s b/crypto/internal/fips140/aes/gcm/gcm_ppc64x.s similarity index 96% rename from crypto/aes/gcm_ppc64x.s rename to crypto/internal/fips140/aes/gcm/gcm_ppc64x.s index 987f4e718e1..558399b10a7 100644 --- a/crypto/aes/gcm_ppc64x.s +++ b/crypto/internal/fips140/aes/gcm/gcm_ppc64x.s @@ -12,7 +12,7 @@ // # details see http://www.openssl.org/~appro/cryptogams/. // # ==================================================================== -// The implementations for gcmHash, gcmInit and gcmMul are based on the generated asm +// The implementations for gcmHash and gcmInit are based on the generated asm // from the script https://github.com/dot-asm/cryptogams/blob/master/ppc/ghashp8-ppc.pl // from commit d47afb3c. @@ -94,6 +94,18 @@ #define ESPERM V10 #define TMP2 V11 +DATA ·rcon+0x00(SB)/8, $0x0f0e0d0c0b0a0908 // Permute for vector doubleword endian swap +DATA ·rcon+0x08(SB)/8, $0x0706050403020100 +DATA ·rcon+0x10(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x18(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x20(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x28(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x30(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x38(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x40(SB)/8, $0x0000000000000000 +DATA ·rcon+0x48(SB)/8, $0x0000000000000000 +GLOBL ·rcon(SB), RODATA, $80 + // The following macros provide appropriate // implementations for endianness as well as // ISA specific for power8 and power9. @@ -833,52 +845,6 @@ done_4x: STXVD2X VXL, (XIP+R0) // write out Xi RET -// func gcmMul(output []byte, productTable *[256]byte) -TEXT ·gcmMul(SB), NOSPLIT, $0-32 - MOVD output+0(FP), XIP - MOVD productTable+24(FP), HTBL - - MOVD $0x10, R8 - MOVD $0x20, R9 - MOVD $0x30, R10 - LXVD2X (XIP)(R0), VIN // load Xi - - LXVD2X (HTBL)(R8), VHL // Load pre-computed table - LXVD2X (HTBL)(R9), VH - LXVD2X (HTBL)(R10), VHH - LXVD2X (HTBL)(R0), VXC2 -#ifdef GOARCH_ppc64le - VSPLTISB $0x07, T0 - VXOR LEMASK, T0, LEMASK - VPERM IN, IN, LEMASK, IN -#endif - VXOR ZERO, ZERO, ZERO - - VPMSUMD IN, HL, XL // H.lo·Xi.lo - VPMSUMD IN, H, XM // H.hi·Xi.lo+H.lo·Xi.hi - VPMSUMD IN, HH, XH // H.hi·Xi.hi - - VPMSUMD XL, XC2, T2 // 1st reduction phase - - VSLDOI $8, XM, ZERO, T0 - VSLDOI $8, ZERO, XM, T1 - VXOR XL, T0, XL - VXOR XH, T1, XH - - VSLDOI $8, XL, XL, XL - VXOR XL, T2, XL - - VSLDOI $8, XL, XL, T1 // 2nd reduction phase - VPMSUMD XL, XC2, XL - VXOR T1, XH, T1 - VXOR XL, T1, XL - -#ifdef GOARCH_ppc64le - VPERM XL, XL, LEMASK, XL -#endif - STXVD2X VXL, (XIP+R0) // write out Xi - RET - #define BLK_INP R3 #define BLK_OUT R4 #define BLK_KEY R5 diff --git a/crypto/internal/fips140/aes/gcm/gcm_s390x.go b/crypto/internal/fips140/aes/gcm/gcm_s390x.go new file mode 100644 index 00000000000..b954f64cd80 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_s390x.go @@ -0,0 +1,251 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// This file contains two implementations of AES-GCM. The first implementation +// (useGHASH) uses the KMCTR instruction to encrypt using AES in counter mode +// and the KIMD instruction for GHASH. The second implementation (useGCM) uses +// the newer KMA instruction which performs both operations (but still requires +// KIMD to hash large nonces). + +// Keep in sync with crypto/tls.hasAESGCMHardwareSupport. +var useGHASH = cpu.S390XHasAES && cpu.S390XHasAESCTR && cpu.S390XHasGHASH +var useGCM = useGHASH && cpu.S390XHasAESGCM + +func init() { + impl.Register("gcm", "CPACF/KIMD", &useGHASH) + impl.Register("gcm", "CPACF/KMA", &useGCM) +} + +func checkGenericIsExpected() { + if useGHASH || useGCM { + panic("gcm: internal error: using generic implementation despite hardware support") + } +} + +// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array. +func gcmLengths(len0, len1 uint64) [16]byte { + v := [16]byte{} + byteorder.BEPutUint64(v[0:], len0) + byteorder.BEPutUint64(v[8:], len1) + return v +} + +// gcmHashKey represents the 16-byte hash key required by the GHASH algorithm. +type gcmHashKey [16]byte + +type gcmPlatformData struct { + hashKey gcmHashKey +} + +func initGCM(g *GCM) { + if !useGCM && !useGHASH { + return + } + // Note that hashKey is also used in the KMA codepath to hash large nonces. + aes.EncryptBlockInternal(&g.cipher, g.hashKey[:], g.hashKey[:]) +} + +// ghashAsm uses the GHASH algorithm to hash data with the given key. The initial +// hash value is given by hash which will be updated with the new hash value. +// The length of data must be a multiple of 16-bytes. +// +//go:noescape +func ghashAsm(key *gcmHashKey, hash *[16]byte, data []byte) + +// paddedGHASH pads data with zeroes until its length is a multiple of +// 16-bytes. It then calculates a new value for hash using the GHASH algorithm. +func paddedGHASH(hashKey *gcmHashKey, hash *[16]byte, data []byte) { + siz := len(data) &^ 0xf // align size to 16-bytes + if siz > 0 { + ghashAsm(hashKey, hash, data[:siz]) + data = data[siz:] + } + if len(data) > 0 { + var s [16]byte + copy(s[:], data) + ghashAsm(hashKey, hash, s[:]) + } +} + +// cryptBlocksGCM encrypts src using AES in counter mode using the given +// function code and key. The rightmost 32-bits of the counter are incremented +// between each block as required by the GCM spec. The initial counter value +// is given by cnt, which is updated with the value of the next counter value +// to use. +// +// The lengths of both dst and buf must be greater than or equal to the length +// of src. buf may be partially or completely overwritten during the execution +// of the function. +// +//go:noescape +func cryptBlocksGCM(fn int, key, dst, src, buf []byte, cnt *[gcmBlockSize]byte) + +// counterCrypt encrypts src using AES in counter mode and places the result +// into dst. cnt is the initial count value and will be updated with the next +// count value. The length of dst must be greater than or equal to the length +// of src. +func counterCrypt(g *GCM, dst, src []byte, cnt *[gcmBlockSize]byte) { + // Copying src into a buffer improves performance on some models when + // src and dst point to the same underlying array. We also need a + // buffer for counter values. + var ctrbuf, srcbuf [2048]byte + for len(src) >= 16 { + siz := len(src) + if len(src) > len(ctrbuf) { + siz = len(ctrbuf) + } + siz &^= 0xf // align siz to 16-bytes + copy(srcbuf[:], src[:siz]) + cryptBlocksGCM(aes.BlockFunction(&g.cipher), aes.BlockKey(&g.cipher), dst[:siz], srcbuf[:siz], ctrbuf[:], cnt) + src = src[siz:] + dst = dst[siz:] + } + if len(src) > 0 { + var x [16]byte + aes.EncryptBlockInternal(&g.cipher, x[:], cnt[:]) + for i := range src { + dst[i] = src[i] ^ x[i] + } + gcmInc32(cnt) + } +} + +// deriveCounter computes the initial GCM counter state from the given nonce. +// See NIST SP 800-38D, section 7.1 and deriveCounterGeneric in gcm_generic.go. +func deriveCounter(H *gcmHashKey, counter *[gcmBlockSize]byte, nonce []byte) { + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + var hash [16]byte + paddedGHASH(H, &hash, nonce) + lens := gcmLengths(0, uint64(len(nonce))*8) + paddedGHASH(H, &hash, lens[:]) + copy(counter[:], hash[:]) + } +} + +// gcmAuth calculates GHASH(additionalData, ciphertext), masks the result +// with tagMask and writes the result to out. +func gcmAuth(out []byte, H *gcmHashKey, tagMask *[gcmBlockSize]byte, ciphertext, additionalData []byte) { + var hash [16]byte + paddedGHASH(H, &hash, additionalData) + paddedGHASH(H, &hash, ciphertext) + lens := gcmLengths(uint64(len(additionalData))*8, uint64(len(ciphertext))*8) + paddedGHASH(H, &hash, lens[:]) + + copy(out, hash[:]) + for i := range out { + out[i] ^= tagMask[i] + } +} + +func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + switch { + case useGCM: + sealKMA(out, g, nonce, plaintext, data) + case useGHASH: + sealAsm(out, g, nonce, plaintext, data) + default: + sealGeneric(out, g, nonce, plaintext, data) + } +} + +func sealAsm(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&g.hashKey, &counter, nonce) + counterCrypt(g, tagMask[:], tagMask[:], &counter) + + counterCrypt(g, out, plaintext, &counter) + + var tag [gcmTagSize]byte + gcmAuth(tag[:], &g.hashKey, &tagMask, out[:len(plaintext)], additionalData) + copy(out[len(plaintext):], tag[:]) +} + +func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + switch { + case useGCM: + return openKMA(out, g, nonce, ciphertext, data) + case useGHASH: + return openAsm(out, g, nonce, ciphertext, data) + default: + return openGeneric(out, g, nonce, ciphertext, data) + } +} + +func openAsm(out []byte, g *GCM, nonce, ciphertext, additionalData []byte) error { + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&g.hashKey, &counter, nonce) + counterCrypt(g, tagMask[:], tagMask[:], &counter) + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var expectedTag [gcmTagSize]byte + gcmAuth(expectedTag[:], &g.hashKey, &tagMask, ciphertext, additionalData) + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + return errOpen + } + + counterCrypt(g, out, ciphertext, &counter) + + return nil +} + +// flags for the KMA instruction +const ( + kmaHS = 1 << 10 // hash subkey supplied + kmaLAAD = 1 << 9 // last series of additional authenticated data + kmaLPC = 1 << 8 // last series of plaintext or ciphertext blocks + kmaDecrypt = 1 << 7 // decrypt +) + +// kmaGCM executes the encryption or decryption operation given by fn. The tag +// will be calculated and written to tag. cnt should contain the current +// counter state and will be overwritten with the updated counter state. +// TODO(mundaym): could pass in hash subkey +// +//go:noescape +func kmaGCM(fn int, key, dst, src, aad []byte, tag *[16]byte, cnt *[gcmBlockSize]byte) + +func sealKMA(out []byte, g *GCM, nonce, plaintext, data []byte) { + var counter [gcmBlockSize]byte + deriveCounter(&g.hashKey, &counter, nonce) + fc := aes.BlockFunction(&g.cipher) | kmaLAAD | kmaLPC + + var tag [gcmTagSize]byte + kmaGCM(fc, aes.BlockKey(&g.cipher), out[:len(plaintext)], plaintext, data, &tag, &counter) + copy(out[len(plaintext):], tag[:]) +} + +func openKMA(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var counter [gcmBlockSize]byte + deriveCounter(&g.hashKey, &counter, nonce) + fc := aes.BlockFunction(&g.cipher) | kmaLAAD | kmaLPC | kmaDecrypt + + var expectedTag [gcmTagSize]byte + kmaGCM(fc, aes.BlockKey(&g.cipher), out[:len(ciphertext)], ciphertext, data, &expectedTag, &counter) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + return errOpen + } + + return nil +} diff --git a/crypto/internal/fips140/aes/gcm/gcm_s390x.s b/crypto/internal/fips140/aes/gcm/gcm_s390x.s new file mode 100644 index 00000000000..23a15dfcb0c --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/gcm_s390x.s @@ -0,0 +1,130 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *[16]byte) +TEXT ·cryptBlocksGCM(SB),NOSPLIT,$0-112 + MOVD src_len+64(FP), R0 + MOVD buf_base+80(FP), R1 + MOVD cnt+104(FP), R12 + LMG (R12), R2, R3 + + // Check that the src size is less than or equal to the buffer size. + MOVD buf_len+88(FP), R4 + CMP R0, R4 + BGT crash + + // Check that the src size is a multiple of 16-bytes. + MOVD R0, R4 + AND $0xf, R4 + BLT crash // non-zero + + // Check that the src size is less than or equal to the dst size. + MOVD dst_len+40(FP), R4 + CMP R0, R4 + BGT crash + + MOVD R2, R4 + MOVD R2, R6 + MOVD R2, R8 + MOVD R3, R5 + MOVD R3, R7 + MOVD R3, R9 + ADDW $1, R5 + ADDW $2, R7 + ADDW $3, R9 +incr: + CMP R0, $64 + BLT tail + STMG R2, R9, (R1) + ADDW $4, R3 + ADDW $4, R5 + ADDW $4, R7 + ADDW $4, R9 + MOVD $64(R1), R1 + SUB $64, R0 + BR incr +tail: + CMP R0, $0 + BEQ crypt + STMG R2, R3, (R1) + ADDW $1, R3 + MOVD $16(R1), R1 + SUB $16, R0 + BR tail +crypt: + STMG R2, R3, (R12) // update next counter value + MOVD fn+0(FP), R0 // function code (encryption) + MOVD key_base+8(FP), R1 // key + MOVD buf_base+80(FP), R2 // counter values + MOVD dst_base+32(FP), R4 // dst + MOVD src_base+56(FP), R6 // src + MOVD src_len+64(FP), R7 // len +loop: + KMCTR R4, R2, R6 // cipher message with counter (KMCTR) + BVS loop // branch back if interrupted + RET +crash: + MOVD $0, (R0) + RET + + +// func ghashAsm(key *gcmHashKey, hash *[16]byte, data []byte) +TEXT ·ghashAsm(SB),NOSPLIT,$32-40 + MOVD $65, R0 // GHASH function code + MOVD key+0(FP), R2 + LMG (R2), R6, R7 + MOVD hash+8(FP), R8 + LMG (R8), R4, R5 + MOVD $params-32(SP), R1 + STMG R4, R7, (R1) + LMG data+16(FP), R2, R3 // R2=base, R3=len +loop: + KIMD R0, R2 // compute intermediate message digest (KIMD) + BVS loop // branch back if interrupted + MVC $16, (R1), (R8) + MOVD $0, R0 + RET + +// func kmaGCM(fn int, key, dst, src, aad []byte, tag *[16]byte, cnt *[gcmBlockSize]byte) +TEXT ·kmaGCM(SB),NOSPLIT,$112-120 + MOVD fn+0(FP), R0 + MOVD $params-112(SP), R1 + + // load ptr/len pairs + LMG dst+32(FP), R2, R3 // R2=base R3=len + LMG src+56(FP), R4, R5 // R4=base R5=len + LMG aad+80(FP), R6, R7 // R6=base R7=len + + // setup parameters + MOVD cnt+112(FP), R8 + XC $12, (R1), (R1) // reserved + MVC $4, 12(R8), 12(R1) // set chain value + MVC $16, (R8), 64(R1) // set initial counter value + XC $32, 16(R1), 16(R1) // set hash subkey and tag + SLD $3, R7, R12 + MOVD R12, 48(R1) // set total AAD length + SLD $3, R5, R12 + MOVD R12, 56(R1) // set total plaintext/ciphertext length + + LMG key+8(FP), R8, R9 // R8=base R9=len + MVC $16, (R8), 80(R1) // set key + CMPBEQ R9, $16, kma + MVC $8, 16(R8), 96(R1) + CMPBEQ R9, $24, kma + MVC $8, 24(R8), 104(R1) + +kma: + KMA R2, R6, R4 // Cipher Message with Authentication + BVS kma + + MOVD tag+104(FP), R2 + MVC $16, 16(R1), 0(R2) // copy tag to output + MOVD cnt+112(FP), R8 + MVC $4, 12(R1), 12(R8) // update counter value + + RET diff --git a/crypto/internal/fips140/aes/gcm/ghash.go b/crypto/internal/fips140/aes/gcm/ghash.go new file mode 100644 index 00000000000..361119dd400 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/ghash.go @@ -0,0 +1,163 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM +// standard and make binary.BigEndian suitable for marshaling these values, the +// bits are stored in big endian order. For example: +// +// the coefficient of x⁰ can be obtained by v.low >> 63. +// the coefficient of x⁶³ can be obtained by v.low & 1. +// the coefficient of x⁶⁴ can be obtained by v.high >> 63. +// the coefficient of x¹²⁷ can be obtained by v.high & 1. +type gcmFieldElement struct { + low, high uint64 +} + +// GHASH is exposed to allow crypto/cipher to implement non-AES GCM modes. +// It is not allowed as a stand-alone operation in FIPS mode because it +// is not ACVP tested. +func GHASH(key *[16]byte, inputs ...[]byte) []byte { + fips140.RecordNonApproved() + var out [gcmBlockSize]byte + ghash(&out, key, inputs...) + return out[:] +} + +// ghash is a variable-time generic implementation of GHASH, which shouldn't +// be used on any architecture with hardware support for AES-GCM. +// +// Each input is zero-padded to 128-bit before being absorbed. +func ghash(out, H *[gcmBlockSize]byte, inputs ...[]byte) { + // productTable contains the first sixteen powers of the key, H. + // However, they are in bit reversed order. + var productTable [16]gcmFieldElement + + // We precompute 16 multiples of H. However, when we do lookups + // into this table we'll be using bits from a field element and + // therefore the bits will be in the reverse order. So normally one + // would expect, say, 4*H to be in index 4 of the table but due to + // this bit ordering it will actually be in index 0010 (base 2) = 2. + x := gcmFieldElement{ + byteorder.BEUint64(H[:8]), + byteorder.BEUint64(H[8:]), + } + productTable[reverseBits(1)] = x + + for i := 2; i < 16; i += 2 { + productTable[reverseBits(i)] = ghashDouble(&productTable[reverseBits(i/2)]) + productTable[reverseBits(i+1)] = ghashAdd(&productTable[reverseBits(i)], &x) + } + + var y gcmFieldElement + for _, input := range inputs { + ghashUpdate(&productTable, &y, input) + } + + byteorder.BEPutUint64(out[:], y.low) + byteorder.BEPutUint64(out[8:], y.high) +} + +// reverseBits reverses the order of the bits of 4-bit number in i. +func reverseBits(i int) int { + i = ((i << 2) & 0xc) | ((i >> 2) & 0x3) + i = ((i << 1) & 0xa) | ((i >> 1) & 0x5) + return i +} + +// ghashAdd adds two elements of GF(2¹²⁸) and returns the sum. +func ghashAdd(x, y *gcmFieldElement) gcmFieldElement { + // Addition in a characteristic 2 field is just XOR. + return gcmFieldElement{x.low ^ y.low, x.high ^ y.high} +} + +// ghashDouble returns the result of doubling an element of GF(2¹²⁸). +func ghashDouble(x *gcmFieldElement) (double gcmFieldElement) { + msbSet := x.high&1 == 1 + + // Because of the bit-ordering, doubling is actually a right shift. + double.high = x.high >> 1 + double.high |= x.low << 63 + double.low = x.low >> 1 + + // If the most-significant bit was set before shifting then it, + // conceptually, becomes a term of x^128. This is greater than the + // irreducible polynomial so the result has to be reduced. The + // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to + // eliminate the term at x^128 which also means subtracting the other + // four terms. In characteristic 2 fields, subtraction == addition == + // XOR. + if msbSet { + double.low ^= 0xe100000000000000 + } + + return +} + +var ghashReductionTable = []uint16{ + 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, +} + +// ghashMul sets y to y*H, where H is the GCM key, fixed during New. +func ghashMul(productTable *[16]gcmFieldElement, y *gcmFieldElement) { + var z gcmFieldElement + + for i := 0; i < 2; i++ { + word := y.high + if i == 1 { + word = y.low + } + + // Multiplication works by multiplying z by 16 and adding in + // one of the precomputed multiples of H. + for j := 0; j < 64; j += 4 { + msw := z.high & 0xf + z.high >>= 4 + z.high |= z.low << 60 + z.low >>= 4 + z.low ^= uint64(ghashReductionTable[msw]) << 48 + + // the values in |table| are ordered for little-endian bit + // positions. See the comment in New. + t := productTable[word&0xf] + + z.low ^= t.low + z.high ^= t.high + word >>= 4 + } + } + + *y = z +} + +// updateBlocks extends y with more polynomial terms from blocks, based on +// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks. +func updateBlocks(productTable *[16]gcmFieldElement, y *gcmFieldElement, blocks []byte) { + for len(blocks) > 0 { + y.low ^= byteorder.BEUint64(blocks) + y.high ^= byteorder.BEUint64(blocks[8:]) + ghashMul(productTable, y) + blocks = blocks[gcmBlockSize:] + } +} + +// ghashUpdate extends y with more polynomial terms from data. If data is not a +// multiple of gcmBlockSize bytes long then the remainder is zero padded. +func ghashUpdate(productTable *[16]gcmFieldElement, y *gcmFieldElement, data []byte) { + fullBlocks := (len(data) >> 4) << 4 + updateBlocks(productTable, y, data[:fullBlocks]) + + if len(data) != fullBlocks { + var partialBlock [gcmBlockSize]byte + copy(partialBlock[:], data[fullBlocks:]) + updateBlocks(productTable, y, partialBlock[:]) + } +} diff --git a/crypto/internal/fips140/aes/gcm/interface_test.go b/crypto/internal/fips140/aes/gcm/interface_test.go new file mode 100644 index 00000000000..935fb673604 --- /dev/null +++ b/crypto/internal/fips140/aes/gcm/interface_test.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcm_test + +import ( + "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes/gcm" +) + +var _ cipher.AEAD = (*gcm.GCM)(nil) diff --git a/crypto/internal/fips140/aes/interface_test.go b/crypto/internal/fips140/aes/interface_test.go new file mode 100644 index 00000000000..ab6c40aaa10 --- /dev/null +++ b/crypto/internal/fips140/aes/interface_test.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes_test + +import ( + "github.com/runZeroInc/excrypto/crypto/cipher" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" +) + +var _ cipher.Block = (*aes.Block)(nil) +var _ cipher.Stream = (*aes.CTR)(nil) +var _ cipher.BlockMode = (*aes.CBCDecrypter)(nil) +var _ cipher.BlockMode = (*aes.CBCEncrypter)(nil) diff --git a/crypto/internal/alias/alias.go b/crypto/internal/fips140/alias/alias.go similarity index 100% rename from crypto/internal/alias/alias.go rename to crypto/internal/fips140/alias/alias.go diff --git a/crypto/subtle/xor_loong64.go b/crypto/internal/fips140/asan.go similarity index 65% rename from crypto/subtle/xor_loong64.go rename to crypto/internal/fips140/asan.go index e49f0fc9e3f..af8f24df811 100644 --- a/crypto/subtle/xor_loong64.go +++ b/crypto/internal/fips140/asan.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego +//go:build asan -package subtle +package fips140 -//go:noescape -func xorBytes(dst, a, b *byte, n int) +const asanEnabled = true diff --git a/crypto/internal/fips140/bigmod/_asm/go.mod b/crypto/internal/fips140/bigmod/_asm/go.mod new file mode 100644 index 00000000000..3c1ae18929b --- /dev/null +++ b/crypto/internal/fips140/bigmod/_asm/go.mod @@ -0,0 +1,10 @@ +module crypto/internal/fips140/bigmod/_asm + +go 1.25 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.14.0 // indirect + golang.org/x/tools v0.16.1 // indirect +) diff --git a/crypto/internal/fips140/bigmod/_asm/go.sum b/crypto/internal/fips140/bigmod/_asm/go.sum new file mode 100644 index 00000000000..483bba88396 --- /dev/null +++ b/crypto/internal/fips140/bigmod/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= diff --git a/crypto/internal/bigmod/_asm/nat_amd64_asm.go b/crypto/internal/fips140/bigmod/_asm/nat_amd64_asm.go similarity index 97% rename from crypto/internal/bigmod/_asm/nat_amd64_asm.go rename to crypto/internal/fips140/bigmod/_asm/nat_amd64_asm.go index 6bc87117ec3..548216dc482 100644 --- a/crypto/internal/bigmod/_asm/nat_amd64_asm.go +++ b/crypto/internal/fips140/bigmod/_asm/nat_amd64_asm.go @@ -15,7 +15,7 @@ import ( //go:generate go run . -out ../nat_amd64.s -pkg bigmod func main() { - Package("github.com/runZeroInc/excrypto/crypto/internal/bigmod") + Package("crypto/internal/fips140/bigmod") ConstraintExpr("!purego") addMulVVW(1024) diff --git a/crypto/internal/bigmod/nat.go b/crypto/internal/fips140/bigmod/nat.go similarity index 63% rename from crypto/internal/bigmod/nat.go rename to crypto/internal/fips140/bigmod/nat.go index 8b2621e6330..5fbb9958655 100644 --- a/crypto/internal/bigmod/nat.go +++ b/crypto/internal/fips140/bigmod/nat.go @@ -6,9 +6,11 @@ package bigmod import ( "errors" - "github.com/runZeroInc/excrypto/internal/byteorder" - "math/big" "math/bits" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" ) const ( @@ -18,6 +20,15 @@ const ( _S = _W / 8 ) +// Note: These functions make many loops over all the words in a Nat. +// These loops used to be in assembly, invisible to -race, -asan, and -msan, +// but now they are in Go and incur significant overhead in those modes. +// To bring the old performance back, we mark all functions that loop +// over Nat words with //go:norace. Because //go:norace does not +// propagate across inlining, we must also mark functions that inline +// //go:norace functions - specifically, those that inline add, addMulVVW, +// assign, cmpGeq, rshift1, and sub. + // choice represents a constant-time boolean. The value of choice is always // either 1 or 0. We use an int instead of bool in order to make decisions in // constant time by turning it into a mask. @@ -92,6 +103,32 @@ func (x *Nat) reset(n int) *Nat { return x } +// resetToBytes assigns x = b, where b is a slice of big-endian bytes, resizing +// n to the appropriate size. +// +// The announced length of x is set based on the actual bit size of the input, +// ignoring leading zeroes. +func (x *Nat) resetToBytes(b []byte) *Nat { + x.reset((len(b) + _S - 1) / _S) + if err := x.setBytes(b); err != nil { + panic("bigmod: internal error: bad arithmetic") + } + return x.trim() +} + +// trim reduces the size of x to match its value. +func (x *Nat) trim() *Nat { + // Trim most significant (trailing in little-endian) zero limbs. + // We assume comparison with zero (but not the branch) is constant time. + for i := len(x.limbs) - 1; i >= 0; i-- { + if x.limbs[i] != 0 { + break + } + x.limbs = x.limbs[:i] + } + return x +} + // set assigns x = y, optionally resizing x to the appropriate size. func (x *Nat) set(y *Nat) *Nat { x.reset(len(y.limbs)) @@ -99,23 +136,17 @@ func (x *Nat) set(y *Nat) *Nat { return x } -// setBig assigns x = n, optionally resizing n to the appropriate size. -// -// The announced length of x is set based on the actual bit size of the input, -// ignoring leading zeroes. -func (x *Nat) setBig(n *big.Int) *Nat { - limbs := n.Bits() - x.reset(len(limbs)) - for i := range limbs { - x.limbs[i] = uint(limbs[i]) - } - return x +// Bits returns x as a little-endian slice of uint. The length of the slice +// matches the announced length of x. The result and x share the same underlying +// array. +func (x *Nat) Bits() []uint { + return x.limbs } // Bytes returns x as a zero-extended big-endian byte slice. The size of the // slice will match the size of m. // -// x must have the same size as m and it must be reduced modulo m. +// x must have the same size as m and it must be less than or equal to m. func (x *Nat) Bytes(m *Modulus) []byte { i := m.Size() bytes := make([]byte, i) @@ -139,8 +170,11 @@ func (x *Nat) Bytes(m *Modulus) []byte { // SetBytes returns an error if b >= m. // // The output will be resized to the size of m and overwritten. +// +//go:norace func (x *Nat) SetBytes(b []byte, m *Modulus) (*Nat, error) { - if err := x.setBytes(b, m); err != nil { + x.resetFor(m) + if err := x.setBytes(b); err != nil { return nil, err } if x.cmpGeq(m.nat) == yes { @@ -155,11 +189,14 @@ func (x *Nat) SetBytes(b []byte, m *Modulus) (*Nat, error) { // // The output will be resized to the size of m and overwritten. func (x *Nat) SetOverflowingBytes(b []byte, m *Modulus) (*Nat, error) { - if err := x.setBytes(b, m); err != nil { + x.resetFor(m) + if err := x.setBytes(b); err != nil { return nil, err } - leading := _W - bitLen(x.limbs[len(x.limbs)-1]) - if leading < m.leading { + // setBytes would have returned an error if the input overflowed the limb + // size of the modulus, so now we only need to check if the most significant + // limb of x has more bits than the most significant limb of the modulus. + if bitLen(x.limbs[len(x.limbs)-1]) > bitLen(m.nat.limbs[len(m.nat.limbs)-1]) { return nil, errors.New("input overflows the modulus size") } x.maybeSubtractModulus(no, m) @@ -170,13 +207,12 @@ func (x *Nat) SetOverflowingBytes(b []byte, m *Modulus) (*Nat, error) { // big-endian encoded uint value. func bigEndianUint(buf []byte) uint { if _W == 64 { - return uint(byteorder.BeUint64(buf)) + return uint(byteorder.BEUint64(buf)) } - return uint(byteorder.BeUint32(buf)) + return uint(byteorder.BEUint32(buf)) } -func (x *Nat) setBytes(b []byte, m *Modulus) error { - x.resetFor(m) +func (x *Nat) setBytes(b []byte) error { i, k := len(b), 0 for k < len(x.limbs) && i >= _S { x.limbs[k] = bigEndianUint(b[i-_S : i]) @@ -193,9 +229,20 @@ func (x *Nat) setBytes(b []byte, m *Modulus) error { return nil } +// SetUint assigns x = y. +// +// The output will be resized to a single limb and overwritten. +func (x *Nat) SetUint(y uint) *Nat { + x.reset(1) + x.limbs[0] = y + return x +} + // Equal returns 1 if x == y, and 0 otherwise. // // Both operands must have the same announced length. +// +//go:norace func (x *Nat) Equal(y *Nat) choice { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -210,6 +257,8 @@ func (x *Nat) Equal(y *Nat) choice { } // IsZero returns 1 if x == 0, and 0 otherwise. +// +//go:norace func (x *Nat) IsZero() choice { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -222,9 +271,65 @@ func (x *Nat) IsZero() choice { return zero } +// IsOne returns 1 if x == 1, and 0 otherwise. +// +//go:norace +func (x *Nat) IsOne() choice { + // Eliminate bounds checks in the loop. + size := len(x.limbs) + xLimbs := x.limbs[:size] + + if len(xLimbs) == 0 { + return no + } + + one := ctEq(xLimbs[0], 1) + for i := 1; i < size; i++ { + one &= ctEq(xLimbs[i], 0) + } + return one +} + +// IsMinusOne returns 1 if x == -1 mod m, and 0 otherwise. +// +// The length of x must be the same as the modulus. x must already be reduced +// modulo m. +// +//go:norace +func (x *Nat) IsMinusOne(m *Modulus) choice { + minusOne := m.Nat() + minusOne.SubOne(m) + return x.Equal(minusOne) +} + +// IsOdd returns 1 if x is odd, and 0 otherwise. +func (x *Nat) IsOdd() choice { + if len(x.limbs) == 0 { + return no + } + return choice(x.limbs[0] & 1) +} + +// TrailingZeroBitsVarTime returns the number of trailing zero bits in x. +func (x *Nat) TrailingZeroBitsVarTime() uint { + var t uint + limbs := x.limbs + for _, l := range limbs { + if l == 0 { + t += _W + continue + } + t += uint(bits.TrailingZeros(l)) + break + } + return t +} + // cmpGeq returns 1 if x >= y, and 0 otherwise. // // Both operands must have the same announced length. +// +//go:norace func (x *Nat) cmpGeq(y *Nat) choice { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -243,6 +348,8 @@ func (x *Nat) cmpGeq(y *Nat) choice { // assign sets x <- y if on == 1, and does nothing otherwise. // // Both operands must have the same announced length. +// +//go:norace func (x *Nat) assign(on choice, y *Nat) *Nat { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -259,6 +366,8 @@ func (x *Nat) assign(on choice, y *Nat) *Nat { // add computes x += y and returns the carry. // // Both operands must have the same announced length. +// +//go:norace func (x *Nat) add(y *Nat) (c uint) { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -274,6 +383,8 @@ func (x *Nat) add(y *Nat) (c uint) { // sub computes x -= y. It returns the borrow of the subtraction. // // Both operands must have the same announced length. +// +//go:norace func (x *Nat) sub(y *Nat) (c uint) { // Eliminate bounds checks in the loop. size := len(x.limbs) @@ -286,21 +397,85 @@ func (x *Nat) sub(y *Nat) (c uint) { return } -// Modulus is used for modular arithmetic, precomputing relevant constants. +// ShiftRightVarTime sets x = x >> n. // -// Moduli are assumed to be odd numbers. Moduli can also leak the exact -// number of bits needed to store their value, and are stored without padding. +// The announced length of x is unchanged. // -// Their actual value is still kept secret. +//go:norace +func (x *Nat) ShiftRightVarTime(n uint) *Nat { + // Eliminate bounds checks in the loop. + size := len(x.limbs) + xLimbs := x.limbs[:size] + + shift := int(n % _W) + shiftLimbs := int(n / _W) + + var shiftedLimbs []uint + if shiftLimbs < size { + shiftedLimbs = xLimbs[shiftLimbs:] + } + + for i := range xLimbs { + if i >= len(shiftedLimbs) { + xLimbs[i] = 0 + continue + } + + xLimbs[i] = shiftedLimbs[i] >> shift + if i+1 < len(shiftedLimbs) { + xLimbs[i] |= shiftedLimbs[i+1] << (_W - shift) + } + } + + return x +} + +// BitLenVarTime returns the actual size of x in bits. +// +// The actual size of x (but nothing more) leaks through timing side-channels. +// Note that this is ordinarily secret, as opposed to the announced size of x. +func (x *Nat) BitLenVarTime() int { + // Eliminate bounds checks in the loop. + size := len(x.limbs) + xLimbs := x.limbs[:size] + + for i := size - 1; i >= 0; i-- { + if xLimbs[i] != 0 { + return i*_W + bitLen(xLimbs[i]) + } + } + return 0 +} + +// bitLen is a version of bits.Len that only leaks the bit length of n, but not +// its value. bits.Len and bits.LeadingZeros use a lookup table for the +// low-order bits on some architectures. +func bitLen(n uint) int { + len := 0 + // We assume, here and elsewhere, that comparison to zero is constant time + // with respect to different non-zero values. + for n != 0 { + len++ + n >>= 1 + } + return len +} + +// Modulus is used for modular arithmetic, precomputing relevant constants. +// +// A Modulus can leak the exact number of bits needed to store its value +// and is stored without padding. Its actual value is still kept secret. type Modulus struct { // The underlying natural number for this modulus. // // This will be stored without any padding, and shouldn't alias with any // other natural number being used. - nat *Nat - leading int // number of leading zeros in the modulus - m0inv uint // -nat.limbs[0]⁻¹ mod _W - rr *Nat // R*R for montgomeryRepresentation + nat *Nat + + // If m is even, the following fields are not set. + odd bool + m0inv uint // -nat.limbs[0]⁻¹ mod _W + rr *Nat // R*R for montgomeryRepresentation } // rr returns R*R with R = 2^(_W * n) and n = len(m.nat.limbs). @@ -369,36 +544,41 @@ func minusInverseModW(x uint) uint { return -y } -// NewModulusFromBig creates a new Modulus from a [big.Int]. +// NewModulus creates a new Modulus from a slice of big-endian bytes. The +// modulus must be greater than one. // -// The Int must be odd. The number of significant bits (and nothing else) is -// leaked through timing side-channels. -func NewModulusFromBig(n *big.Int) (*Modulus, error) { - if b := n.Bits(); len(b) == 0 { - return nil, errors.New("modulus must be >= 0") - } else if b[0]&1 != 1 { - return nil, errors.New("modulus must be odd") +// The number of significant bits and whether the modulus is even is leaked +// through timing side-channels. +func NewModulus(b []byte) (*Modulus, error) { + n := NewNat().resetToBytes(b) + return newModulus(n) +} + +// NewModulusProduct creates a new Modulus from the product of two numbers +// represented as big-endian byte slices. The result must be greater than one. +// +//go:norace +func NewModulusProduct(a, b []byte) (*Modulus, error) { + x := NewNat().resetToBytes(a) + y := NewNat().resetToBytes(b) + n := NewNat().reset(len(x.limbs) + len(y.limbs)) + for i := range y.limbs { + n.limbs[i+len(x.limbs)] = addMulVVW(n.limbs[i:i+len(x.limbs)], x.limbs, y.limbs[i]) } - m := &Modulus{} - m.nat = NewNat().setBig(n) - m.leading = _W - bitLen(m.nat.limbs[len(m.nat.limbs)-1]) - m.m0inv = minusInverseModW(m.nat.limbs[0]) - m.rr = rr(m) - return m, nil + return newModulus(n.trim()) } -// bitLen is a version of bits.Len that only leaks the bit length of n, but not -// its value. bits.Len and bits.LeadingZeros use a lookup table for the -// low-order bits on some architectures. -func bitLen(n uint) int { - var len int - // We assume, here and elsewhere, that comparison to zero is constant time - // with respect to different non-zero values. - for n != 0 { - len++ - n >>= 1 +func newModulus(n *Nat) (*Modulus, error) { + m := &Modulus{nat: n} + if m.nat.IsZero() == yes || m.nat.IsOne() == yes { + return nil, errors.New("modulus must be > 1") } - return len + if m.nat.IsOdd() == 1 { + m.odd = true + m.m0inv = minusInverseModW(m.nat.limbs[0]) + m.rr = rr(m) + } + return m, nil } // Size returns the size of m in bytes. @@ -408,17 +588,23 @@ func (m *Modulus) Size() int { // BitLen returns the size of m in bits. func (m *Modulus) BitLen() int { - return len(m.nat.limbs)*_W - int(m.leading) + return m.nat.BitLenVarTime() } -// Nat returns m as a Nat. The return value must not be written to. +// Nat returns m as a Nat. func (m *Modulus) Nat() *Nat { - return m.nat + // Make a copy so that the caller can't modify m.nat or alias it with + // another Nat in a modulus operation. + n := NewNat() + n.set(m.nat) + return n } // shiftIn calculates x = x << _W + y mod m. // // This assumes that x is already reduced mod m. +// +//go:norace func (x *Nat) shiftIn(y uint, m *Modulus) *Nat { d := NewNat().resetFor(m) @@ -458,6 +644,8 @@ func (x *Nat) shiftIn(y uint, m *Modulus) *Nat { // This works regardless how large the value of x is. // // The output will be resized to the size of m and overwritten. +// +//go:norace func (out *Nat) Mod(x *Nat, m *Modulus) *Nat { out.resetFor(m) // Working our way from the most significant to the least significant limb, @@ -507,6 +695,8 @@ func (out *Nat) resetFor(m *Modulus) *Nat { // overflowed its size, meaning abstractly x > 2^_W*n > m even if x < m. // // x and m operands must have the same announced length. +// +//go:norace func (x *Nat) maybeSubtractModulus(always choice, m *Modulus) { t := NewNat().set(x) underflow := t.sub(m.nat) @@ -520,6 +710,8 @@ func (x *Nat) maybeSubtractModulus(always choice, m *Modulus) { // // The length of both operands must be the same as the modulus. Both operands // must already be reduced modulo m. +// +//go:norace func (x *Nat) Sub(y *Nat, m *Modulus) *Nat { underflow := x.sub(y) // If the subtraction underflowed, add m. @@ -529,10 +721,23 @@ func (x *Nat) Sub(y *Nat, m *Modulus) *Nat { return x } +// SubOne computes x = x - 1 mod m. +// +// The length of x must be the same as the modulus. +func (x *Nat) SubOne(m *Modulus) *Nat { + one := NewNat().ExpandFor(m) + one.limbs[0] = 1 + // Sub asks for x to be reduced modulo m, while SubOne doesn't, but when + // y = 1, it works, and this is an internal use. + return x.Sub(one, m) +} + // Add computes x = x + y mod m. // // The length of both operands must be the same as the modulus. Both operands // must already be reduced modulo m. +// +//go:norace func (x *Nat) Add(y *Nat, m *Modulus) *Nat { overflow := x.add(y) x.maybeSubtractModulus(choice(overflow), m) @@ -570,6 +775,8 @@ func (x *Nat) montgomeryReduction(m *Modulus) *Nat { // // All inputs should be the same length and already reduced modulo m. // x will be resized to the size of m and overwritten. +// +//go:norace func (x *Nat) montgomeryMul(a *Nat, b *Nat, m *Modulus) *Nat { n := len(m.nat.limbs) mLimbs := m.nat.limbs[:n] @@ -691,6 +898,8 @@ func (x *Nat) montgomeryMul(a *Nat, b *Nat, m *Modulus) *Nat { // addMulVVW multiplies the multi-word value x by the single-word value y, // adding the result to the multi-word value z and returning the final carry. // It can be thought of as one row of a pen-and-paper column multiplication. +// +//go:norace func addMulVVW(z, x []uint, y uint) (carry uint) { _ = x[len(z)-1] // bounds check elimination hint for i := range z { @@ -711,18 +920,76 @@ func addMulVVW(z, x []uint, y uint) (carry uint) { // // The length of both operands must be the same as the modulus. Both operands // must already be reduced modulo m. +// +//go:norace func (x *Nat) Mul(y *Nat, m *Modulus) *Nat { - // A Montgomery multiplication by a value out of the Montgomery domain - // takes the result out of Montgomery representation. - xR := NewNat().set(x).montgomeryRepresentation(m) // xR = x * R mod m - return x.montgomeryMul(xR, y, m) // x = xR * y / R mod m + if m.odd { + // A Montgomery multiplication by a value out of the Montgomery domain + // takes the result out of Montgomery representation. + xR := NewNat().set(x).montgomeryRepresentation(m) // xR = x * R mod m + return x.montgomeryMul(xR, y, m) // x = xR * y / R mod m + } + + n := len(m.nat.limbs) + xLimbs := x.limbs[:n] + yLimbs := y.limbs[:n] + + switch n { + default: + // Attempt to use a stack-allocated backing array. + T := make([]uint, 0, preallocLimbs*2) + if cap(T) < n*2 { + T = make([]uint, 0, n*2) + } + T = T[:n*2] + + // T = x * y + for i := 0; i < n; i++ { + T[n+i] = addMulVVW(T[i:n+i], xLimbs, yLimbs[i]) + } + + // x = T mod m + return x.Mod(&Nat{limbs: T}, m) + + // The following specialized cases follow the exact same algorithm, but + // optimized for the sizes most used in RSA. See montgomeryMul for details. + case 1024 / _W: + const n = 1024 / _W // compiler hint + T := make([]uint, n*2) + for i := 0; i < n; i++ { + T[n+i] = addMulVVW1024(&T[i], &xLimbs[0], yLimbs[i]) + } + return x.Mod(&Nat{limbs: T}, m) + case 1536 / _W: + const n = 1536 / _W // compiler hint + T := make([]uint, n*2) + for i := 0; i < n; i++ { + T[n+i] = addMulVVW1536(&T[i], &xLimbs[0], yLimbs[i]) + } + return x.Mod(&Nat{limbs: T}, m) + case 2048 / _W: + const n = 2048 / _W // compiler hint + T := make([]uint, n*2) + for i := 0; i < n; i++ { + T[n+i] = addMulVVW2048(&T[i], &xLimbs[0], yLimbs[i]) + } + return x.Mod(&Nat{limbs: T}, m) + } } // Exp calculates out = x^e mod m. // // The exponent e is represented in big-endian order. The output will be resized // to the size of m and overwritten. x must already be reduced modulo m. +// +// m must be odd, or Exp will panic. +// +//go:norace func (out *Nat) Exp(x *Nat, e []byte, m *Modulus) *Nat { + if !m.odd { + panic("bigmod: modulus for Exp must be odd") + } + // We use a 4 bit window. For our RSA workload, 4 bit windows are faster // than 2 bit windows, but use an extra 12 nats worth of scratch space. // Using bit sizes that don't divide 8 are more complex to implement, but @@ -771,13 +1038,18 @@ func (out *Nat) Exp(x *Nat, e []byte, m *Modulus) *Nat { // // The output will be resized to the size of m and overwritten. x must already // be reduced modulo m. This leaks the exponent through timing side-channels. +// +// m must be odd, or ExpShortVarTime will panic. func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat { + if !m.odd { + panic("bigmod: modulus for ExpShortVarTime must be odd") + } // For short exponents, precomputing a table and using a window like in Exp // doesn't pay off. Instead, we do a simple conditional square-and-multiply // chain, skipping the initial run of zeroes. xR := NewNat().set(x).montgomeryRepresentation(m) out.set(xR) - for i := bits.UintSize - bitLen(e) + 1; i < bits.UintSize; i++ { + for i := bits.UintSize - bits.Len(e) + 1; i < bits.UintSize; i++ { out.montgomeryMul(out, out, m) if k := (e >> (bits.UintSize - i - 1)) & 1; k != 0 { out.montgomeryMul(out, xR, m) @@ -785,3 +1057,174 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat { } return out.montgomeryReduction(m) } + +// InverseVarTime calculates x = a⁻¹ mod m and returns (x, true) if a is +// invertible. Otherwise, InverseVarTime returns (x, false) and x is not +// modified. +// +// a must be reduced modulo m, but doesn't need to have the same size. The +// output will be resized to the size of m and overwritten. +// +//go:norace +func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + u, A, err := extendedGCD(a, m.nat) + if err != nil { + return x, false + } + if u.IsOne() == no { + return x, false + } + return x.set(A), true +} + +// GCDVarTime calculates x = GCD(a, b) where at least one of a or b is odd, and +// both are non-zero. If GCDVarTime returns an error, x is not modified. +// +// The output will be resized to the size of the larger of a and b. +func (x *Nat) GCDVarTime(a, b *Nat) (*Nat, error) { + u, _, err := extendedGCD(a, b) + if err != nil { + return nil, err + } + return x.set(u), nil +} + +// extendedGCD computes u and A such that a = GCD(a, m) and u = A*a - B*m. +// +// u will have the size of the larger of a and m, and A will have the size of m. +// +// It is an error if either a or m is zero, or if they are both even. +func extendedGCD(a, m *Nat) (u, A *Nat, err error) { + // This is the extended binary GCD algorithm described in the Handbook of + // Applied Cryptography, Algorithm 14.61, adapted by BoringSSL to bound + // coefficients and avoid negative numbers. For more details and proof of + // correctness, see https://github.com/mit-plv/fiat-crypto/pull/333/files. + // + // Following the proof linked in the PR above, the changes are: + // + // 1. Negate [B] and [C] so they are positive. The invariant now involves a + // subtraction. + // 2. If step 2 (both [x] and [y] are even) runs, abort immediately. This + // case needs to be handled by the caller. + // 3. Subtract copies of [x] and [y] as needed in step 6 (both [u] and [v] + // are odd) so coefficients stay in bounds. + // 4. Replace the [u >= v] check with [u > v]. This changes the end + // condition to [v = 0] rather than [u = 0]. This saves an extra + // subtraction due to which coefficients were negated. + // 5. Rename x and y to a and n, to capture that one is a modulus. + // 6. Rearrange steps 4 through 6 slightly. Merge the loops in steps 4 and + // 5 into the main loop (step 7's goto), and move step 6 to the start of + // the loop iteration, ensuring each loop iteration halves at least one + // value. + // + // Note this algorithm does not handle either input being zero. + + if a.IsZero() == yes || m.IsZero() == yes { + return nil, nil, errors.New("extendedGCD: a or m is zero") + } + if a.IsOdd() == no && m.IsOdd() == no { + return nil, nil, errors.New("extendedGCD: both a and m are even") + } + + size := max(len(a.limbs), len(m.limbs)) + u = NewNat().set(a).expand(size) + v := NewNat().set(m).expand(size) + + A = NewNat().reset(len(m.limbs)) + A.limbs[0] = 1 + B := NewNat().reset(len(a.limbs)) + C := NewNat().reset(len(m.limbs)) + D := NewNat().reset(len(a.limbs)) + D.limbs[0] = 1 + + // Before and after each loop iteration, the following hold: + // + // u = A*a - B*m + // v = D*m - C*a + // 0 < u <= a + // 0 <= v <= m + // 0 <= A < m + // 0 <= B <= a + // 0 <= C < m + // 0 <= D <= a + // + // After each loop iteration, u and v only get smaller, and at least one of + // them shrinks by at least a factor of two. + for { + // If both u and v are odd, subtract the smaller from the larger. + // If u = v, we need to subtract from v to hit the modified exit condition. + if u.IsOdd() == yes && v.IsOdd() == yes { + if v.cmpGeq(u) == no { + u.sub(v) + A.Add(C, &Modulus{nat: m}) + B.Add(D, &Modulus{nat: a}) + } else { + v.sub(u) + C.Add(A, &Modulus{nat: m}) + D.Add(B, &Modulus{nat: a}) + } + } + + // Exactly one of u and v is now even. + if u.IsOdd() == v.IsOdd() { + panic("bigmod: internal error: u and v are not in the expected state") + } + + // Halve the even one and adjust the corresponding coefficient. + if u.IsOdd() == no { + rshift1(u, 0) + if A.IsOdd() == yes || B.IsOdd() == yes { + rshift1(A, A.add(m)) + rshift1(B, B.add(a)) + } else { + rshift1(A, 0) + rshift1(B, 0) + } + } else { // v.IsOdd() == no + rshift1(v, 0) + if C.IsOdd() == yes || D.IsOdd() == yes { + rshift1(C, C.add(m)) + rshift1(D, D.add(a)) + } else { + rshift1(C, 0) + rshift1(D, 0) + } + } + + if v.IsZero() == yes { + return u, A, nil + } + } +} + +//go:norace +func rshift1(a *Nat, carry uint) { + size := len(a.limbs) + aLimbs := a.limbs[:size] + + for i := range size { + aLimbs[i] >>= 1 + if i+1 < size { + aLimbs[i] |= aLimbs[i+1] << (_W - 1) + } else { + aLimbs[i] |= carry << (_W - 1) + } + } +} + +// DivShortVarTime calculates x = x / y and returns the remainder. +// +// It panics if y is zero. +// +//go:norace +func (x *Nat) DivShortVarTime(y uint) uint { + if y == 0 { + panic("bigmod: division by zero") + } + + var r uint + for i := len(x.limbs) - 1; i >= 0; i-- { + x.limbs[i], r = bits.Div(r, x.limbs[i], y) + } + return r +} diff --git a/crypto/internal/bigmod/nat_386.s b/crypto/internal/fips140/bigmod/nat_386.s similarity index 85% rename from crypto/internal/bigmod/nat_386.s rename to crypto/internal/fips140/bigmod/nat_386.s index b66f33fe054..e724c794c68 100644 --- a/crypto/internal/bigmod/nat_386.s +++ b/crypto/internal/fips140/bigmod/nat_386.s @@ -9,19 +9,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB), $0-16 MOVL $32, BX - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB), $0-16 MOVL $48, BX - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB), $0-16 MOVL $64, BX - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB), NOFRAME|NOSPLIT, $0 +TEXT addMulVVWxExcrypto(SB), NOFRAME|NOSPLIT, $0 MOVL z+0(FP), DI MOVL x+4(FP), SI MOVL y+8(FP), BP diff --git a/crypto/internal/bigmod/nat_amd64.s b/crypto/internal/fips140/bigmod/nat_amd64.s similarity index 100% rename from crypto/internal/bigmod/nat_amd64.s rename to crypto/internal/fips140/bigmod/nat_amd64.s diff --git a/crypto/internal/bigmod/nat_arm.s b/crypto/internal/fips140/bigmod/nat_arm.s similarity index 85% rename from crypto/internal/bigmod/nat_arm.s rename to crypto/internal/fips140/bigmod/nat_arm.s index d89f51461df..1529be7f1c6 100644 --- a/crypto/internal/bigmod/nat_arm.s +++ b/crypto/internal/fips140/bigmod/nat_arm.s @@ -9,19 +9,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB), $0-16 MOVW $32, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB), $0-16 MOVW $48, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB), $0-16 MOVW $64, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB), NOFRAME|NOSPLIT, $0 +TEXT addMulVVWxExcrypto(SB), NOFRAME|NOSPLIT, $0 MOVW $0, R0 MOVW z+0(FP), R1 MOVW x+4(FP), R2 diff --git a/crypto/internal/bigmod/nat_arm64.s b/crypto/internal/fips140/bigmod/nat_arm64.s similarity index 91% rename from crypto/internal/bigmod/nat_arm64.s rename to crypto/internal/fips140/bigmod/nat_arm64.s index c6b3593cc15..ca4da1b3079 100644 --- a/crypto/internal/bigmod/nat_arm64.s +++ b/crypto/internal/fips140/bigmod/nat_arm64.s @@ -9,19 +9,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB), $0-32 MOVD $16, R0 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB), $0-32 MOVD $24, R0 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB), $0-32 MOVD $32, R0 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB), NOFRAME|NOSPLIT, $0 +TEXT addMulVVWxExcrypto(SB), NOFRAME|NOSPLIT, $0 MOVD z+0(FP), R1 MOVD x+8(FP), R2 MOVD y+16(FP), R3 diff --git a/crypto/internal/bigmod/nat_asm.go b/crypto/internal/fips140/bigmod/nat_asm.go similarity index 77% rename from crypto/internal/bigmod/nat_asm.go rename to crypto/internal/fips140/bigmod/nat_asm.go index b92892edded..42276c35d9c 100644 --- a/crypto/internal/bigmod/nat_asm.go +++ b/crypto/internal/fips140/bigmod/nat_asm.go @@ -6,7 +6,10 @@ package bigmod -import "github.com/runZeroInc/excrypto/internal/cpu" +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) // amd64 assembly uses ADCX/ADOX/MULX if ADX is available to run two carry // chains in the flags in parallel across the whole operation, and aggressively @@ -16,7 +19,13 @@ import "github.com/runZeroInc/excrypto/internal/cpu" // amd64 without ADX, perform better than the compiler output. // TODO(filippo): file cmd/compile performance issue. -var supportADX = cpu.X86.HasADX && cpu.X86.HasBMI2 +var supportADX = cpu.X86HasADX && cpu.X86HasBMI2 + +func init() { + if cpu.AMD64 { + impl.Register("aes", "ADX", &supportADX) + } +} //go:noescape func addMulVVW1024(z, x *uint, y uint) (c uint) diff --git a/crypto/internal/bigmod/nat_loong64.s b/crypto/internal/fips140/bigmod/nat_loong64.s similarity index 92% rename from crypto/internal/bigmod/nat_loong64.s rename to crypto/internal/fips140/bigmod/nat_loong64.s index db93a1ea9f6..4d3560007a5 100644 --- a/crypto/internal/bigmod/nat_loong64.s +++ b/crypto/internal/fips140/bigmod/nat_loong64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// derived from crypto/internal/bigmod/nat_riscv64.s +// derived from crypto/internal/fips140/bigmod/nat_riscv64.s //go:build !purego @@ -11,19 +11,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB),$0-32 MOVV $16, R8 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB),$0-32 MOVV $24, R8 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB),$0-32 MOVV $32, R8 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB),NOFRAME|NOSPLIT,$0 +TEXT addMulVVWxExcrypto(SB),NOFRAME|NOSPLIT,$0 MOVV z+0(FP), R4 MOVV x+8(FP), R6 MOVV y+16(FP), R5 diff --git a/crypto/internal/bigmod/nat_noasm.go b/crypto/internal/fips140/bigmod/nat_noasm.go similarity index 92% rename from crypto/internal/bigmod/nat_noasm.go rename to crypto/internal/fips140/bigmod/nat_noasm.go index 2501a6fb4ce..dbec229f5d2 100644 --- a/crypto/internal/bigmod/nat_noasm.go +++ b/crypto/internal/fips140/bigmod/nat_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build purego || !(386 || amd64 || arm || arm64 || loong64 || ppc64 || ppc64le || riscv64 || s390x) +//go:build purego || !(386 || amd64 || arm || arm64 || loong64 || ppc64 || ppc64le || riscv64 || s390x || wasm) package bigmod diff --git a/crypto/internal/bigmod/nat_ppc64x.s b/crypto/internal/fips140/bigmod/nat_ppc64x.s similarity index 93% rename from crypto/internal/bigmod/nat_ppc64x.s rename to crypto/internal/fips140/bigmod/nat_ppc64x.s index eac02b74b75..cc615edde9f 100644 --- a/crypto/internal/bigmod/nat_ppc64x.s +++ b/crypto/internal/fips140/bigmod/nat_ppc64x.s @@ -9,17 +9,17 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB), $0-32 MOVD $4, R6 // R6 = z_len/4 - JMP addMulVVWxExCrypto<>(SB) + JMP addMulVVWxExcrypto<>(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB), $0-32 MOVD $6, R6 // R6 = z_len/4 - JMP addMulVVWxExCrypto<>(SB) + JMP addMulVVWxExcrypto<>(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB), $0-32 MOVD $8, R6 // R6 = z_len/4 - JMP addMulVVWxExCrypto<>(SB) + JMP addMulVVWxExcrypto<>(SB) // This local function expects to be called only by // callers above. R6 contains the z length/4 @@ -27,7 +27,7 @@ TEXT ·addMulVVW2048(SB), $0-32 // loop iteration, and is guaranteed to be > 0. // If other callers are added this function might // need to change. -TEXT addMulVVWxExCrypto<>(SB), NOSPLIT, $0 +TEXT addMulVVWxExcrypto<>(SB), NOSPLIT, $0 MOVD z+0(FP), R3 MOVD x+8(FP), R4 MOVD y+16(FP), R5 diff --git a/crypto/internal/bigmod/nat_riscv64.s b/crypto/internal/fips140/bigmod/nat_riscv64.s similarity index 94% rename from crypto/internal/bigmod/nat_riscv64.s rename to crypto/internal/fips140/bigmod/nat_riscv64.s index 8ce4f19caa7..3230492de13 100644 --- a/crypto/internal/bigmod/nat_riscv64.s +++ b/crypto/internal/fips140/bigmod/nat_riscv64.s @@ -9,19 +9,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB),$0-32 MOV $16, X30 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB),$0-32 MOV $24, X30 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB),$0-32 MOV $32, X30 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB),NOFRAME|NOSPLIT,$0 +TEXT addMulVVWxExcrypto(SB),NOFRAME|NOSPLIT,$0 MOV z+0(FP), X5 MOV x+8(FP), X7 MOV y+16(FP), X6 diff --git a/crypto/internal/bigmod/nat_s390x.s b/crypto/internal/fips140/bigmod/nat_s390x.s similarity index 91% rename from crypto/internal/bigmod/nat_s390x.s rename to crypto/internal/fips140/bigmod/nat_s390x.s index 9248619b6cf..7e918f2f565 100644 --- a/crypto/internal/bigmod/nat_s390x.s +++ b/crypto/internal/fips140/bigmod/nat_s390x.s @@ -9,19 +9,19 @@ // func addMulVVW1024(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1024(SB), $0-32 MOVD $16, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW1536(z, x *uint, y uint) (c uint) TEXT ·addMulVVW1536(SB), $0-32 MOVD $24, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) // func addMulVVW2048(z, x *uint, y uint) (c uint) TEXT ·addMulVVW2048(SB), $0-32 MOVD $32, R5 - JMP addMulVVWxExCrypto(SB) + JMP addMulVVWxExcrypto(SB) -TEXT addMulVVWxExCrypto(SB), NOFRAME|NOSPLIT, $0 +TEXT addMulVVWxExcrypto(SB), NOFRAME|NOSPLIT, $0 MOVD z+0(FP), R2 MOVD x+8(FP), R8 MOVD y+16(FP), R9 diff --git a/crypto/internal/bigmod/nat_test.go b/crypto/internal/fips140/bigmod/nat_test.go similarity index 60% rename from crypto/internal/bigmod/nat_test.go rename to crypto/internal/fips140/bigmod/nat_test.go index 7a956e3a57d..36ea559d977 100644 --- a/crypto/internal/bigmod/nat_test.go +++ b/crypto/internal/fips140/bigmod/nat_test.go @@ -5,16 +5,43 @@ package bigmod import ( + "bufio" + "bytes" + cryptorand "crypto/rand" + "encoding/hex" "fmt" "math/big" "math/bits" "math/rand" + "os" "reflect" + "slices" "strings" "testing" "testing/quick" ) +// setBig assigns x = n, optionally resizing n to the appropriate size. +// +// The announced length of x is set based on the actual bit size of the input, +// ignoring leading zeroes. +func (x *Nat) setBig(n *big.Int) *Nat { + limbs := n.Bits() + x.reset(len(limbs)) + for i := range limbs { + x.limbs[i] = uint(limbs[i]) + } + return x +} + +func (n *Nat) asBig() *big.Int { + bits := make([]big.Word, len(n.limbs)) + for i := range n.limbs { + bits[i] = big.Word(n.limbs[i]) + } + return new(big.Int).SetBits(bits) +} + func (n *Nat) String() string { var limbs []string for i := range n.limbs { @@ -70,7 +97,7 @@ func TestMontgomeryRoundtrip(t *testing.T) { one.limbs[0] = 1 aPlusOne := new(big.Int).SetBytes(natBytes(a)) aPlusOne.Add(aPlusOne, big.NewInt(1)) - m, _ := NewModulusFromBig(aPlusOne) + m, _ := NewModulus(aPlusOne.Bytes()) monty := new(Nat).set(a) monty.montgomeryRepresentation(m) aAgain := new(Nat).set(monty) @@ -319,7 +346,7 @@ func TestMulReductions(t *testing.T) { b, _ := new(big.Int).SetString("180692823610368451951102211649591374573781973061758082626801", 10) n := new(big.Int).Mul(a, b) - N, _ := NewModulusFromBig(n) + N, _ := NewModulus(n.Bytes()) A := NewNat().setBig(a).ExpandFor(N) B := NewNat().setBig(b).ExpandFor(N) @@ -328,7 +355,7 @@ func TestMulReductions(t *testing.T) { } i := new(big.Int).ModInverse(a, b) - N, _ = NewModulusFromBig(b) + N, _ = NewModulus(b.Bytes()) A = NewNat().setBig(a).ExpandFor(N) I := NewNat().setBig(i).ExpandFor(N) one := NewNat().setBig(big.NewInt(1)).ExpandFor(N) @@ -338,6 +365,148 @@ func TestMulReductions(t *testing.T) { } } +func TestMul(t *testing.T) { + t.Run("small", func(t *testing.T) { testMul(t, 760/8) }) + t.Run("1024", func(t *testing.T) { testMul(t, 1024/8) }) + t.Run("1536", func(t *testing.T) { testMul(t, 1536/8) }) + t.Run("2048", func(t *testing.T) { testMul(t, 2048/8) }) +} + +func testMul(t *testing.T, n int) { + a, b, m := make([]byte, n), make([]byte, n), make([]byte, n) + cryptorand.Read(a) + cryptorand.Read(b) + cryptorand.Read(m) + + // Pick the highest as the modulus. + if bytes.Compare(a, m) > 0 { + a, m = m, a + } + if bytes.Compare(b, m) > 0 { + b, m = m, b + } + + M, err := NewModulus(m) + if err != nil { + t.Fatal(err) + } + A, err := NewNat().SetBytes(a, M) + if err != nil { + t.Fatal(err) + } + B, err := NewNat().SetBytes(b, M) + if err != nil { + t.Fatal(err) + } + + A.Mul(B, M) + ABytes := A.Bytes(M) + + mBig := new(big.Int).SetBytes(m) + aBig := new(big.Int).SetBytes(a) + bBig := new(big.Int).SetBytes(b) + nBig := new(big.Int).Mul(aBig, bBig) + nBig.Mod(nBig, mBig) + nBigBytes := make([]byte, len(ABytes)) + nBig.FillBytes(nBigBytes) + + if !bytes.Equal(ABytes, nBigBytes) { + t.Errorf("got %x, want %x", ABytes, nBigBytes) + } +} + +func TestIs(t *testing.T) { + checkYes := func(c choice, err string) { + t.Helper() + if c != yes { + t.Error(err) + } + } + checkNot := func(c choice, err string) { + t.Helper() + if c != no { + t.Error(err) + } + } + + mFour := modulusFromBytes([]byte{4}) + n, err := NewNat().SetBytes([]byte{3}, mFour) + if err != nil { + t.Fatal(err) + } + checkYes(n.IsMinusOne(mFour), "3 is not -1 mod 4") + checkNot(n.IsZero(), "3 is zero") + checkNot(n.IsOne(), "3 is one") + checkYes(n.IsOdd(), "3 is not odd") + n.SubOne(mFour) + checkNot(n.IsMinusOne(mFour), "2 is -1 mod 4") + checkNot(n.IsZero(), "2 is zero") + checkNot(n.IsOne(), "2 is one") + checkNot(n.IsOdd(), "2 is odd") + n.SubOne(mFour) + checkNot(n.IsMinusOne(mFour), "1 is -1 mod 4") + checkNot(n.IsZero(), "1 is zero") + checkYes(n.IsOne(), "1 is not one") + checkYes(n.IsOdd(), "1 is not odd") + n.SubOne(mFour) + checkNot(n.IsMinusOne(mFour), "0 is -1 mod 4") + checkYes(n.IsZero(), "0 is not zero") + checkNot(n.IsOne(), "0 is one") + checkNot(n.IsOdd(), "0 is odd") + n.SubOne(mFour) + checkYes(n.IsMinusOne(mFour), "-1 is not -1 mod 4") + checkNot(n.IsZero(), "-1 is zero") + checkNot(n.IsOne(), "-1 is one") + checkYes(n.IsOdd(), "-1 mod 4 is not odd") + + mTwoLimbs := maxModulus(2) + n, err = NewNat().SetBytes([]byte{0x01}, mTwoLimbs) + if err != nil { + t.Fatal(err) + } + if n.IsOne() != 1 { + t.Errorf("1 is not one") + } +} + +func TestTrailingZeroBits(t *testing.T) { + nb := new(big.Int).SetBytes([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e}) + nb.Lsh(nb, 128) + expected := 129 + for expected >= 0 { + n := NewNat().setBig(nb) + if n.TrailingZeroBitsVarTime() != uint(expected) { + t.Errorf("%d != %d", n.TrailingZeroBitsVarTime(), expected) + } + nb.Rsh(nb, 1) + expected-- + } +} + +func TestRightShift(t *testing.T) { + nb, err := cryptorand.Int(cryptorand.Reader, new(big.Int).Lsh(big.NewInt(1), 1024)) + if err != nil { + t.Fatal(err) + } + for _, shift := range []uint{1, 32, 64, 128, 1024 - 128, 1024 - 64, 1024 - 32, 1024 - 1} { + testShift := func(t *testing.T, shift uint) { + n := NewNat().setBig(nb) + oldLen := len(n.limbs) + n.ShiftRightVarTime(shift) + if len(n.limbs) != oldLen { + t.Errorf("len(n.limbs) = %d, want %d", len(n.limbs), oldLen) + } + exp := new(big.Int).Rsh(nb, shift) + if n.asBig().Cmp(exp) != 0 { + t.Errorf("%v != %v", n.asBig(), exp) + } + } + t.Run(fmt.Sprint(shift-1), func(t *testing.T) { testShift(t, shift-1) }) + t.Run(fmt.Sprint(shift), func(t *testing.T) { testShift(t, shift) }) + t.Run(fmt.Sprint(shift+1), func(t *testing.T) { testShift(t, shift+1) }) + } +} + func natBytes(n *Nat) []byte { return n.Bytes(maxModulus(uint(len(n.limbs)))) } @@ -350,7 +519,7 @@ func natFromBytes(b []byte) *Nat { func modulusFromBytes(b []byte) *Modulus { bb := new(big.Int).SetBytes(b) - m, _ := NewModulusFromBig(bb) + m, _ := NewModulus(bb.Bytes()) return m } @@ -359,7 +528,7 @@ func maxModulus(n uint) *Modulus { b := big.NewInt(1) b.Lsh(b, n*_W) b.Sub(b, big.NewInt(1)) - m, _ := NewModulusFromBig(b) + m, _ := NewModulus(b.Bytes()) return m } @@ -465,16 +634,131 @@ func BenchmarkExp(b *testing.B) { } } -func TestNewModFromBigZero(t *testing.T) { - expected := "modulus must be >= 0" - _, err := NewModulusFromBig(big.NewInt(0)) +func TestNewModulus(t *testing.T) { + expected := "modulus must be > 1" + _, err := NewModulus([]byte{}) if err == nil || err.Error() != expected { - t.Errorf("NewModulusFromBig(0) got %q, want %q", err, expected) + t.Errorf("NewModulus(0) got %q, want %q", err, expected) } - - expected = "modulus must be odd" - _, err = NewModulusFromBig(big.NewInt(2)) + _, err = NewModulus([]byte{0}) + if err == nil || err.Error() != expected { + t.Errorf("NewModulus(0) got %q, want %q", err, expected) + } + _, err = NewModulus([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) if err == nil || err.Error() != expected { - t.Errorf("NewModulusFromBig(2) got %q, want %q", err, expected) + t.Errorf("NewModulus(0) got %q, want %q", err, expected) + } + _, err = NewModulus([]byte{1}) + if err == nil || err.Error() != expected { + t.Errorf("NewModulus(1) got %q, want %q", err, expected) + } + _, err = NewModulus([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) + if err == nil || err.Error() != expected { + t.Errorf("NewModulus(1) got %q, want %q", err, expected) + } +} + +func makeTestValue(nbits int) []uint { + n := nbits / _W + x := make([]uint, n) + for i := range n { + x[i]-- + } + return x +} + +func TestAddMulVVWSized(t *testing.T) { + // Sized addMulVVW have architecture-specific implementations on + // a number of architectures. Test that they match the generic + // implementation. + tests := []struct { + n int + f func(z, x *uint, y uint) uint + }{ + {1024, addMulVVW1024}, + {1536, addMulVVW1536}, + {2048, addMulVVW2048}, + } + for _, test := range tests { + t.Run(fmt.Sprint(test.n), func(t *testing.T) { + x := makeTestValue(test.n) + z := makeTestValue(test.n) + z2 := slices.Clone(z) + var y uint + y-- + c := addMulVVW(z, x, y) + c2 := test.f(&z2[0], &x[0], y) + if !slices.Equal(z, z2) || c != c2 { + t.Errorf("%016X, %016X != %016X, %016X", z, c, z2, c2) + } + }) + } +} + +func TestInverse(t *testing.T) { + f, err := os.Open("testdata/mod_inv_tests.txt") + if err != nil { + t.Fatal(err) + } + + var ModInv, A, M string + var lineNum int + scanner := bufio.NewScanner(f) + for scanner.Scan() { + lineNum++ + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + + k, v, _ := strings.Cut(line, " = ") + switch k { + case "ModInv": + ModInv = v + case "A": + A = v + case "M": + M = v + + t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) { + m, err := NewModulus(decodeHex(t, M)) + if err != nil { + t.Skip("modulus <= 1") + } + a, err := NewNat().SetBytes(decodeHex(t, A), m) + if err != nil { + t.Fatal(err) + } + + got, ok := NewNat().InverseVarTime(a, m) + if !ok { + t.Fatal("not invertible") + } + exp, err := NewNat().SetBytes(decodeHex(t, ModInv), m) + if err != nil { + t.Fatal(err) + } + if got.Equal(exp) != 1 { + t.Errorf("%v != %v", got, exp) + } + }) + default: + t.Fatalf("unknown key %q on line %d", k, lineNum) + } + } + if err := scanner.Err(); err != nil { + t.Fatal(err) + } +} + +func decodeHex(t *testing.T, s string) []byte { + t.Helper() + if len(s)%2 != 0 { + s = "0" + s + } + b, err := hex.DecodeString(s) + if err != nil { + t.Fatalf("failed to decode hex %q: %v", s, err) } + return b } diff --git a/crypto/internal/fips140/bigmod/nat_wasm.go b/crypto/internal/fips140/bigmod/nat_wasm.go new file mode 100644 index 00000000000..b4aaff74cf0 --- /dev/null +++ b/crypto/internal/fips140/bigmod/nat_wasm.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package bigmod + +import "unsafe" + +// The generic implementation relies on 64x64->128 bit multiplication and +// 64-bit add-with-carry, which are compiler intrinsics on many architectures. +// Wasm doesn't support those. Here we implement it with 32x32->64 bit +// operations, which is more efficient on Wasm. + +func idx(x *uint, i uintptr) *uint { + return (*uint)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + i*8)) +} + +func addMulVVWWasm(z, x *uint, y uint, n uintptr) (carry uint) { + const mask32 = 1<<32 - 1 + y0 := y & mask32 + y1 := y >> 32 + for i := range n { + xi := *idx(x, i) + x0 := xi & mask32 + x1 := xi >> 32 + zi := *idx(z, i) + z0 := zi & mask32 + z1 := zi >> 32 + c0 := carry & mask32 + c1 := carry >> 32 + + w00 := x0*y0 + z0 + c0 + l00 := w00 & mask32 + h00 := w00 >> 32 + + w01 := x0*y1 + z1 + h00 + l01 := w01 & mask32 + h01 := w01 >> 32 + + w10 := x1*y0 + c1 + l01 + h10 := w10 >> 32 + + carry = x1*y1 + h10 + h01 + *idx(z, i) = w10<<32 + l00 + } + return carry +} + +func addMulVVW1024(z, x *uint, y uint) (c uint) { + return addMulVVWWasm(z, x, y, 1024/_W) +} + +func addMulVVW1536(z, x *uint, y uint) (c uint) { + return addMulVVWWasm(z, x, y, 1536/_W) +} + +func addMulVVW2048(z, x *uint, y uint) (c uint) { + return addMulVVWWasm(z, x, y, 2048/_W) +} diff --git a/crypto/internal/fips140/bigmod/testdata/mod_inv_tests.txt b/crypto/internal/fips140/bigmod/testdata/mod_inv_tests.txt new file mode 100644 index 00000000000..4ebc1966574 --- /dev/null +++ b/crypto/internal/fips140/bigmod/testdata/mod_inv_tests.txt @@ -0,0 +1,115 @@ +# ModInv tests. +# +# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M. + +ModInv = 00 +A = 00 +M = 01 + +ModInv = 00 +A = 01 +M = 01 + +ModInv = 00 +A = 02 +M = 01 + +ModInv = 00 +A = 03 +M = 01 + +ModInv = 64 +A = 54 +M = e3 + +ModInv = 13 +A = 2b +M = 30 + +ModInv = 2f +A = 30 +M = 37 + +ModInv = 4 +A = 13 +M = 4b + +ModInv = 1c47 +A = cd4 +M = 6a21 + +ModInv = 2b97 +A = 8e7 +M = 49c0 + +ModInv = 29b9 +A = fcb +M = 3092 + +ModInv = a83 +A = 14bf +M = 41ae + +ModInv = 18f15fe1 +A = 11b5d53e +M = 322e92a1 + +ModInv = 32f9453b +A = 8af6df6 +M = 33d45eb7 + +ModInv = d696369 +A = c5f89dd5 +M = fc09c17c + +ModInv = 622839d8 +A = 60c2526 +M = 74200493 + +ModInv = fb5a8aee7bbc4ef +A = 24ebd835a70be4e2 +M = 9c7256574e0c5e93 + +ModInv = 846bc225402419c +A = 23026003ab1fbdb +M = 1683cbe32779c59b + +ModInv = 5ff84f63a78982f9 +A = 4a2420dc733e1a0f +M = a73c6bfabefa09e6 + +ModInv = 133e74d28ef42b43 +A = 2e9511ae29cdd41 +M = 15234df99f19fcda + +ModInv = 46ae1fabe9521e4b99b198fc8439609023aa69be2247c0d1e27c2a0ea332f9c5 +A = 6331fec5f01014046788c919ed50dc86ac7a80c085f1b6f645dd179c0f0dc9cd +M = 8ef409de82318259a8655a39293b1e762fa2cc7e0aeb4c59713a1e1fff6af640 + +ModInv = 444ccea3a7b21677dd294d34de53cc8a5b51e69b37782310a00fc6bcc975709b +A = 679280bd880994c08322143a4ea8a0825d0466fda1bb6b3eb86fc8e90747512b +M = e4fecab84b365c63a0dab4244ce3f921a9c87ec64d69a2031939f55782e99a2e + +ModInv = 1ac7d7a03ceec5f690f567c9d61bf3469c078285bcc5cf00ac944596e887ca17 +A = 1593ef32d9c784f5091bdff952f5c5f592a3aed6ba8ea865efa6d7df87be1805 +M = 1e276882f90c95e0c1976eb079f97af075445b1361c02018d6bd7191162e67b2 + +ModInv = 639108b90dfe946f498be21303058413bbb0e59d0bd6a6115788705abd0666d6 +A = 9258d6238e4923d120b2d1033573ffcac691526ad0842a3b174dccdbb79887bd +M = ce62909c39371d463aaba3d4b72ea6da49cb9b529e39e1972ef3ccd9a66fe08f + +ModInv = aebde7654cb17833a106231c4b9e2f519140e85faee1bfb4192830f03f385e773c0f4767e93e874ffdc3b7a6b7e6a710e5619901c739ee8760a26128e8c91ef8cf761d0e505d8b28ae078d17e6071c372893bb7b72538e518ebc57efa70b7615e406756c49729b7c6e74f84aed7a316b6fa748ff4b9f143129d29dad1bff98bb +A = a29dacaf5487d354280fdd2745b9ace4cd50f2bde41d0ee529bf26a1913244f708085452ff32feab19a7418897990da46a0633f7c8375d583367319091bbbe069b0052c5e48a7daac9fb650db5af768cd2508ec3e2cda7456d4b9ce1c39459627a8b77e038b826cd7e326d0685b0cd0cb50f026f18300dae9f5fd42aa150ee8b +M = d686f9b86697313251685e995c09b9f1e337ddfaa050bd2df15bf4ca1dc46c5565021314765299c434ea1a6ec42bf92a29a7d1ffff599f4e50b79a82243fb24813060580c770d4c1140aeb2ab2685007e948b6f1f62e8001a0545619477d498132c907774479f6d95899e6251e7136f79ab6d3b7c82e4aca421e7d22fe7db19c + +ModInv = 1ec872f4f20439e203597ca4de9d1296743f95781b2fe85d5def808558bbadef02a46b8955f47c83e1625f8bb40228eab09cad2a35c9ad62ab77a30e3932872959c5898674162da244a0ec1f68c0ed89f4b0f3572bfdc658ad15bf1b1c6e1176b0784c9935bd3ff1f49bb43753eacee1d8ca1c0b652d39ec727da83984fe3a0f +A = 2e527b0a1dc32460b2dd94ec446c692989f7b3c7451a5cbeebf69fc0ea9c4871fbe78682d5dc5b66689f7ed889b52161cd9830b589a93d21ab26dbede6c33959f5a0f0d107169e2daaac78bac8cf2d41a1eb1369cb6dc9e865e73bb2e51b886f4e896082db199175e3dde0c4ed826468f238a77bd894245d0918efc9ca84f945 +M = b13133a9ebe0645f987d170c077eea2aa44e85c9ab10386d02867419a590cb182d9826a882306c212dbe75225adde23f80f5b37ca75ed09df20fc277cc7fbbfac8d9ef37a50f6b68ea158f5447283618e64e1426406d26ea85232afb22bf546c75018c1c55cb84c374d58d9d44c0a13ba88ac2e387765cb4c3269e3a983250fa + +ModInv = 30ffa1876313a69de1e4e6ee132ea1d3a3da32f3b56f5cfb11402b0ad517dce605cf8e91d69fa375dd887fa8507bd8a28b2d5ce745799126e86f416047709f93f07fbd88918a047f13100ea71b1d48f6fc6d12e5c917646df3041b302187af641eaedf4908abc36f12c204e1526a7d80e96e302fb0779c28d7da607243732f26 +A = 31157208bde6b85ebecaa63735947b3b36fa351b5c47e9e1c40c947339b78bf96066e5dbe21bb42629e6fcdb81f5f88db590bfdd5f4c0a6a0c3fc6377e5c1fd8235e46e291c688b6d6ecfb36604891c2a7c9cbcc58c26e44b43beecb9c5044b58bb58e35de3cf1128f3c116534fe4e421a33f83603c3df1ae36ec88092f67f2a +M = 53408b23d6cb733e6c9bc3d1e2ea2286a5c83cc4e3e7470f8af3a1d9f28727f5b1f8ae348c1678f5d1105dc3edf2de64e65b9c99545c47e64b770b17c8b4ef5cf194b43a0538053e87a6b95ade1439cebf3d34c6aa72a11c1497f58f76011e16c5be087936d88aba7a740113120e939e27bd3ddcb6580c2841aa406566e33c35 + +ModInv = 87355002f305c81ba0dc97ca2234a2bc02528cefde38b94ac5bd95efc7bf4c140899107fff47f0df9e3c6aa70017ebc90610a750f112cd4f475b9c76b204a953444b4e7196ccf17e93fdaed160b7345ca9b397eddf9446e8ea8ee3676102ce70eaafbe9038a34639789e6f2f1e3f352638f2e8a8f5fc56aaea7ec705ee068dd5 +A = 42a25d0bc96f71750f5ac8a51a1605a41b506cca51c9a7ecf80cad713e56f70f1b4b6fa51cbb101f55fd74f318adefb3af04e0c8a7e281055d5a40dd40913c0e1211767c5be915972c73886106dc49325df6c2df49e9eea4536f0343a8e7d332c6159e4f5bdb20d89f90e67597c4a2a632c31b2ef2534080a9ac61f52303990d +M = d3d3f95d50570351528a76ab1e806bae1968bd420899bdb3d87c823fac439a4354c31f6c888c939784f18fe10a95e6d203b1901caa18937ba6f8be033af10c35fc869cf3d16bef479f280f53b3499e645d0387554623207ca4989e5de00bfeaa5e9ab56474fc60dd4967b100e0832eaaf2fcb2ef82a181567057b880b3afef62 diff --git a/crypto/internal/fips140/boring.go b/crypto/internal/fips140/boring.go new file mode 100644 index 00000000000..d627bc68903 --- /dev/null +++ b/crypto/internal/fips140/boring.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Keep in sync with notboring.go and crypto/internal/boring/boring.go. +//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo + +package fips140 + +const boringEnabled = true diff --git a/crypto/internal/fips140/cast.go b/crypto/internal/fips140/cast.go new file mode 100644 index 00000000000..816cd4b71d7 --- /dev/null +++ b/crypto/internal/fips140/cast.go @@ -0,0 +1,86 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140 + +import ( + "errors" + "fmt" + "os" + "strings" + _ "unsafe" // for go:linkname + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" +) + +// fatal is [runtime.fatal], pushed via linkname. +func fatal(n string) { + fmt.Fprintf(os.Stderr, "fips fatal: %s\n", n) + os.Exit(1) +} + +// failfipscast is a GODEBUG key allowing simulation of a CAST or PCT failure, +// as required during FIPS 140-3 functional testing. The value is the whole name +// of the target CAST or PCT. +var failfipscast = godebug.Value("#failfipscast") + +// CAST runs the named Cryptographic Algorithm Self-Test (if operated in FIPS +// mode) and aborts the program (stopping the module input/output and entering +// the "error state") if the self-test fails. +// +// CASTs are mandatory self-checks that must be performed by FIPS 140-3 modules +// before the algorithm is used. See Implementation Guidance 10.3.A. +// +// The name must not contain commas, colons, hashes, or equal signs. +// +// If a package p calls CAST from its init function, an import of p should also +// be added to crypto/internal/fips140test. If a package p calls CAST on the first +// use of the algorithm, an invocation of that algorithm should be added to +// fipstest.TestConditionals. +func CAST(name string, f func() error) { + if strings.ContainsAny(name, ",#=:") { + panic("fips: invalid self-test name: " + name) + } + if !Enabled { + return + } + + err := f() + if name == failfipscast { + err = errors.New("simulated CAST failure") + } + if err != nil { + fatal("FIPS 140-3 self-test failed: " + name + ": " + err.Error()) + panic("unreachable") + } + if debug { + println("FIPS 140-3 self-test passed:", name) + } +} + +// PCT runs the named Pairwise Consistency Test (if operated in FIPS mode) and +// returns any errors. If an error is returned, the key must not be used. +// +// PCTs are mandatory for every key pair that is generated/imported, including +// ephemeral keys (which effectively doubles the cost of key establishment). See +// Implementation Guidance 10.3.A Additional Comment 1. +// +// The name must not contain commas, colons, hashes, or equal signs. +// +// If a package p calls PCT during key generation, an invocation of that +// function should be added to fipstest.TestConditionals. +func PCT(name string, f func() error) error { + if strings.ContainsAny(name, ",#=:") { + panic("fips: invalid self-test name: " + name) + } + if !Enabled { + return nil + } + + err := f() + if name == failfipscast { + err = errors.New("simulated PCT failure") + } + return err +} diff --git a/crypto/internal/fips140/check/check.go b/crypto/internal/fips140/check/check.go new file mode 100644 index 00000000000..29c76118200 --- /dev/null +++ b/crypto/internal/fips140/check/check.go @@ -0,0 +1,109 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package check implements the FIPS 140 load-time code+data verification. +// Every FIPS package providing cryptographic functionality except hmac and sha256 +// must import crypto/internal/fips140/check, so that the verification happens +// before initialization of package global variables. +// The hmac and sha256 packages are used by this package, so they cannot import it. +// Instead, those packages must be careful not to change global variables during init. +// (If necessary, we could have check call a PostCheck function in those packages +// after the check has completed.) +package check + +import ( + "io" + "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" +) + +// Verified is set when verification succeeded. It can be expected to always be +// true when [fips140.Enabled] is true, or init would have panicked. +var Verified bool + +// Linkinfo holds the go:fipsinfo symbol prepared by the linker. +// See cmd/link/internal/ld/fips.go for details. +// +//go:linkname Linkinfo go:fipsinfo +var Linkinfo struct { + Magic [16]byte + Sum [32]byte + Self uintptr + Sects [4]struct { + // Note: These must be unsafe.Pointer, not uintptr, + // or else checkptr panics about turning uintptrs + // into pointers into the data segment during + // go test -race. + Start unsafe.Pointer + End unsafe.Pointer + } +} + +// "\xff"+fipsMagic is the expected linkinfo.Magic. +// We avoid writing that explicitly so that the string does not appear +// elsewhere in normal binaries, just as a precaution. +const fipsMagic = " Go fipsinfo \xff\x00" + +var zeroSum [32]byte + +func init() { + if !fips140.Enabled { + return + } + + if err := fips140.Supported(); err != nil { + panic("fips140: " + err.Error()) + } + + if Linkinfo.Magic[0] != 0xff || string(Linkinfo.Magic[1:]) != fipsMagic || Linkinfo.Sum == zeroSum { + panic("fips140: no verification checksum found") + } + + h := hmac.New(sha256.New, make([]byte, 32)) + w := io.Writer(h) + + /* + // Uncomment for debugging. + // Commented (as opposed to a const bool flag) + // to avoid import "os" in default builds. + f, err := os.Create("fipscheck.o") + if err != nil { + panic(err) + } + w = io.MultiWriter(h, f) + */ + + w.Write([]byte("go fips object v1\n")) + + var nbuf [8]byte + for _, sect := range Linkinfo.Sects { + n := uintptr(sect.End) - uintptr(sect.Start) + byteorder.BEPutUint64(nbuf[:], uint64(n)) + w.Write(nbuf[:]) + w.Write(unsafe.Slice((*byte)(sect.Start), n)) + } + sum := h.Sum(nil) + + if [32]byte(sum) != Linkinfo.Sum { + panic("fips140: verification mismatch") + } + + // "The temporary value(s) generated during the integrity test of the + // module’s software or firmware shall [05.10] be zeroised from the module + // upon completion of the integrity test" + clear(sum) + clear(nbuf[:]) + h.Reset() + + if godebug.Value("fips140") == "debug" { + println("fips140: verified code+data") + } + + Verified = true +} diff --git a/crypto/internal/fips140/check/checktest/asm.s b/crypto/internal/fips140/check/checktest/asm.s new file mode 100644 index 00000000000..cc74e56f981 --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm.s @@ -0,0 +1,10 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego && !wasm + +#include "textflag.h" + +DATA crypto∕internal∕fips140∕check∕checktest·RODATA(SB)/4, $2 +GLOBL crypto∕internal∕fips140∕check∕checktest·RODATA(SB), RODATA, $4 diff --git a/crypto/internal/fips140/check/checktest/asm_386.s b/crypto/internal/fips140/check/checktest/asm_386.s new file mode 100644 index 00000000000..c2978b51624 --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_386.s @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +DATA StaticData<>(SB)/4, $10 +GLOBL StaticData<>(SB), NOPTR, $4 + +TEXT StaticText<>(SB), $0 + RET + +TEXT ·PtrStaticData(SB), $0-4 + MOVL $StaticData<>(SB), AX + MOVL AX, ret+0(FP) + RET + +TEXT ·PtrStaticText(SB), $0-4 + MOVL $StaticText<>(SB), AX + MOVL AX, ret+0(FP) + RET diff --git a/crypto/internal/fips140/check/checktest/asm_amd64.s b/crypto/internal/fips140/check/checktest/asm_amd64.s new file mode 100644 index 00000000000..88e4d94074c --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_amd64.s @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +DATA StaticData<>(SB)/4, $10 +GLOBL StaticData<>(SB), NOPTR, $4 + +TEXT StaticText<>(SB), $0 + RET + +TEXT ·PtrStaticData(SB), $0-8 + MOVQ $StaticData<>(SB), AX + MOVQ AX, ret+0(FP) + RET + +TEXT ·PtrStaticText(SB), $0-8 + MOVQ $StaticText<>(SB), AX + MOVQ AX, ret+0(FP) + RET diff --git a/crypto/internal/fips140/check/checktest/asm_arm.s b/crypto/internal/fips140/check/checktest/asm_arm.s new file mode 100644 index 00000000000..5cc9230100f --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_arm.s @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +DATA StaticData<>(SB)/4, $10 +GLOBL StaticData<>(SB), NOPTR, $4 + +TEXT StaticText<>(SB), $0 + RET + +TEXT ·PtrStaticData(SB), $0-4 + MOVW $StaticData<>(SB), R1 + MOVW R1, ret+0(FP) + RET + +TEXT ·PtrStaticText(SB), $0-4 + MOVW $StaticText<>(SB), R1 + MOVW R1, ret+0(FP) + RET diff --git a/crypto/internal/fips140/check/checktest/asm_arm64.s b/crypto/internal/fips140/check/checktest/asm_arm64.s new file mode 100644 index 00000000000..721bb03ada5 --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_arm64.s @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +DATA StaticData<>(SB)/4, $10 +GLOBL StaticData<>(SB), NOPTR, $4 + +TEXT StaticText<>(SB), $0 + RET + +TEXT ·PtrStaticData(SB), $0-8 + MOVD $StaticData<>(SB), R1 + MOVD R1, ret+0(FP) + RET + +TEXT ·PtrStaticText(SB), $0-8 + MOVD $StaticText<>(SB), R1 + MOVD R1, ret+0(FP) + RET diff --git a/crypto/internal/fips140/check/checktest/asm_none.go b/crypto/internal/fips140/check/checktest/asm_none.go new file mode 100644 index 00000000000..956bad1cdad --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_none.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!386 && !amd64 && !arm && !arm64) || purego + +package checktest + +import "unsafe" + +func PtrStaticData() *uint32 { return nil } +func PtrStaticText() unsafe.Pointer { return nil } diff --git a/crypto/internal/fips140/check/checktest/asm_stub.go b/crypto/internal/fips140/check/checktest/asm_stub.go new file mode 100644 index 00000000000..ebb5b17b28f --- /dev/null +++ b/crypto/internal/fips140/check/checktest/asm_stub.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (386 || amd64 || arm || arm64) && !purego + +package checktest + +import "unsafe" + +func PtrStaticData() *uint32 +func PtrStaticText() unsafe.Pointer diff --git a/crypto/internal/fips140/check/checktest/test.go b/crypto/internal/fips140/check/checktest/test.go new file mode 100644 index 00000000000..5de69596808 --- /dev/null +++ b/crypto/internal/fips140/check/checktest/test.go @@ -0,0 +1,63 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package checktest defines some code and data for use in +// the crypto/internal/fips140/check test. +package checktest + +import ( + "runtime" + _ "unsafe" // go:linkname + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" +) + +var NOPTRDATA int = 1 + +// The linkname here disables asan registration of this global, +// because asan gets mad about rodata globals. +// +//go:linkname RODATA crypto/internal/fips140/check/checktest.RODATA +var RODATA int32 // set to 2 in asm.s + +// DATA needs to have both a pointer and an int so that _some_ of it gets +// initialized at link time, so it is treated as DATA and not BSS. +// The pointer is deferred to init time. +var DATA = struct { + P *int + X int +}{&NOPTRDATA, 3} + +var NOPTRBSS int + +var BSS *int + +func TEXT() {} + +var ( + globl12 [12]byte + globl8 [8]byte +) + +func init() { + globl8 = [8]byte{1, 2, 3, 4, 5, 6, 7, 8} + globl12 = [12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} + runtime.Gosched() + + sum := byte(0) + for _, x := range globl12 { + sum += x + } + if sum != 78 { + panic("globl12 did not sum properly") + } + + sum = byte(0) + for _, x := range globl8 { + sum += x + } + if sum != 36 { + panic("globl8 did not sum properly") + } +} diff --git a/crypto/internal/fips140/drbg/cast.go b/crypto/internal/fips140/drbg/cast.go new file mode 100644 index 00000000000..977979a48d3 --- /dev/null +++ b/crypto/internal/fips140/drbg/cast.go @@ -0,0 +1,60 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package drbg + +import ( + "bytes" + "errors" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + // Per IG 10.3.A, Resolution 7: "A KAT of a DRBG may be performed by: + // Instantiate with known data, Reseed with other known data, Generate and + // then compare the result to a pre-computed value." + fips140.CAST("CTR_DRBG", func() error { + entropy := &[SeedSize]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + } + reseedEntropy := &[SeedSize]byte{ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + } + additionalInput := &[SeedSize]byte{ + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + } + want := []byte{ + 0x6e, 0x6e, 0x47, 0x9d, 0x24, 0xf8, 0x6a, 0x3b, + 0x77, 0x87, 0xa8, 0xf8, 0x18, 0x6d, 0x98, 0x5a, + 0x53, 0xbe, 0xbe, 0xed, 0xde, 0xab, 0x92, 0x28, + 0xf0, 0xf4, 0xac, 0x6e, 0x10, 0xbf, 0x01, 0x93, + } + c := NewCounter(entropy) + c.Reseed(reseedEntropy, additionalInput) + got := make([]byte, len(want)) + c.Generate(got, additionalInput) + if !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/drbg/ctrdrbg.go b/crypto/internal/fips140/drbg/ctrdrbg.go new file mode 100644 index 00000000000..d28c8d76cf3 --- /dev/null +++ b/crypto/internal/fips140/drbg/ctrdrbg.go @@ -0,0 +1,144 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package drbg + +import ( + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// Counter is an SP 800-90A Rev. 1 CTR_DRBG instantiated with AES-256. +// +// Per Table 3, it has a security strength of 256 bits, a seed size of 384 bits, +// a counter length of 128 bits, a reseed interval of 2^48 requests, and a +// maximum request size of 2^19 bits (2^16 bytes, 64 KiB). +// +// We support a narrow range of parameters that fit the needs of our RNG: +// AES-256, no derivation function, no personalization string, no prediction +// resistance, and 384-bit additional input. +// +// WARNING: this type provides tightly scoped support for the DRBG +// functionality we need for FIPS 140-3 _only_. This type _should not_ be used +// outside of the FIPS 140-3 module for any other use. +// +// In particular, as documented, Counter does not support the derivation +// function, or personalization strings which are necessary for safely using +// this DRBG for generic purposes without leaking sensitive values. +type Counter struct { + // c is instantiated with K as the key and V as the counter. + c aes.CTR + + reseedCounter uint64 +} + +const ( + keySize = 256 / 8 + SeedSize = keySize + aes.BlockSize + reseedInterval = 1 << 48 + maxRequestSize = (1 << 19) / 8 +) + +func NewCounter(entropy *[SeedSize]byte) *Counter { + // CTR_DRBG_Instantiate_algorithm, per Section 10.2.1.3.1. + fips140.RecordApproved() + + K := make([]byte, keySize) + V := make([]byte, aes.BlockSize) + + // V starts at 0, but is incremented in CTR_DRBG_Update before each use, + // unlike AES-CTR where it is incremented after each use. + V[len(V)-1] = 1 + + cipher, err := aes.New(K) + if err != nil { + panic(err) + } + + c := &Counter{} + c.c = *aes.NewCTR(cipher, V) + c.update(entropy) + c.reseedCounter = 1 + return c +} + +func (c *Counter) update(seed *[SeedSize]byte) { + // CTR_DRBG_Update, per Section 10.2.1.2. + + temp := make([]byte, SeedSize) + c.c.XORKeyStream(temp, seed[:]) + K := temp[:keySize] + V := temp[keySize:] + + // Again, we pre-increment V, like in NewCounter. + increment((*[aes.BlockSize]byte)(V)) + + cipher, err := aes.New(K) + if err != nil { + panic(err) + } + c.c = *aes.NewCTR(cipher, V) +} + +func increment(v *[aes.BlockSize]byte) { + hi := byteorder.BEUint64(v[:8]) + lo := byteorder.BEUint64(v[8:]) + lo, c := bits.Add64(lo, 1, 0) + hi, _ = bits.Add64(hi, 0, c) + byteorder.BEPutUint64(v[:8], hi) + byteorder.BEPutUint64(v[8:], lo) +} + +func (c *Counter) Reseed(entropy, additionalInput *[SeedSize]byte) { + // CTR_DRBG_Reseed_algorithm, per Section 10.2.1.4.1. + fips140.RecordApproved() + + var seed [SeedSize]byte + subtle.XORBytes(seed[:], entropy[:], additionalInput[:]) + c.update(&seed) + c.reseedCounter = 1 +} + +// Generate produces at most maxRequestSize bytes of random data in out. +func (c *Counter) Generate(out []byte, additionalInput *[SeedSize]byte) (reseedRequired bool) { + // CTR_DRBG_Generate_algorithm, per Section 10.2.1.5.1. + fips140.RecordApproved() + + if len(out) > maxRequestSize { + panic("crypto/drbg: internal error: request size exceeds maximum") + } + + // Step 1. + if c.reseedCounter > reseedInterval { + return true + } + + // Step 2. + if additionalInput != nil { + c.update(additionalInput) + } else { + // If the additional input is null, the first CTR_DRBG_Update is + // skipped, but the additional input is replaced with an all-zero string + // for the second CTR_DRBG_Update. + additionalInput = new([SeedSize]byte) + } + + // Steps 3-5. + clear(out) + c.c.XORKeyStream(out, out) + aes.RoundToBlock(&c.c) + + // Step 6. + c.update(additionalInput) + + // Step 7. + c.reseedCounter++ + + // Step 8. + return false +} diff --git a/crypto/internal/fips140/drbg/rand.go b/crypto/internal/fips140/drbg/rand.go new file mode 100644 index 00000000000..8feeac8e946 --- /dev/null +++ b/crypto/internal/fips140/drbg/rand.go @@ -0,0 +1,101 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package drbg provides cryptographically secure random bytes +// usable by FIPS code. In FIPS mode it uses an SP 800-90A Rev. 1 +// Deterministic Random Bit Generator (DRBG). Otherwise, +// it uses the operating system's random number generator. +package drbg + +import ( + "crypto/rand" + "io" + "sync" + + "github.com/runZeroInc/excrypto/crypto/internal/entropy" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/randutil" +) + +var drbgs = sync.Pool{ + New: func() any { + var c *Counter + entropy.Depleted(func(seed *[48]byte) { + c = NewCounter(seed) + }) + return c + }, +} + +// Read fills b with cryptographically secure random bytes. In FIPS mode, it +// uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG). +// Otherwise, it uses the operating system's random number generator. +func Read(b []byte) { + if !fips140.Enabled { + rand.Read(b) + return + } + + // At every read, 128 random bits from the operating system are mixed as + // additional input, to make the output as strong as non-FIPS randomness. + // This is not credited as entropy for FIPS purposes, as allowed by Section + // 8.7.2: "Note that a DRBG does not rely on additional input to provide + // entropy, even though entropy could be provided in the additional input". + additionalInput := new([SeedSize]byte) + rand.Read(additionalInput[:16]) + + drbg := drbgs.Get().(*Counter) + defer drbgs.Put(drbg) + + for len(b) > 0 { + size := min(len(b), maxRequestSize) + if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired { + // See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in + // Section 9.3.2: if Generate reports a reseed is required, the + // additional input is passed to Reseed along with the entropy and + // then nulled before the next Generate call. + entropy.Depleted(func(seed *[48]byte) { + drbg.Reseed(seed, additionalInput) + }) + additionalInput = nil + continue + } + b = b[size:] + } +} + +// DefaultReader is a sentinel type, embedded in the default +// [crypto/rand.Reader], used to recognize it when passed to +// APIs that accept a rand io.Reader. +type DefaultReader interface{ defaultReader() } + +// ReadWithReader uses Reader to fill b with cryptographically secure random +// bytes. It is intended for use in APIs that expose a rand io.Reader. +// +// If Reader is not the default Reader from crypto/rand, +// [randutil.MaybeReadByte] and [fips140.RecordNonApproved] are called. +func ReadWithReader(r io.Reader, b []byte) error { + if _, ok := r.(DefaultReader); ok { + Read(b) + return nil + } + + fips140.RecordNonApproved() + randutil.MaybeReadByte(r) + _, err := io.ReadFull(r, b) + return err +} + +// ReadWithReaderDeterministic is like ReadWithReader, but it doesn't call +// [randutil.MaybeReadByte] on non-default Readers. +func ReadWithReaderDeterministic(r io.Reader, b []byte) error { + if _, ok := r.(DefaultReader); ok { + Read(b) + return nil + } + + fips140.RecordNonApproved() + _, err := io.ReadFull(r, b) + return err +} diff --git a/crypto/internal/fips140/drbg/rand_test.go b/crypto/internal/fips140/drbg/rand_test.go new file mode 100644 index 00000000000..bc10691df38 --- /dev/null +++ b/crypto/internal/fips140/drbg/rand_test.go @@ -0,0 +1,28 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package drbg + +import ( + "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func BenchmarkDBRG(b *testing.B) { + old := fips140.Enabled + defer func() { + fips140.Enabled = old + }() + fips140.Enabled = true + + const N = 64 + b.SetBytes(N) + b.RunParallel(func(pb *testing.PB) { + buf := make([]byte, N) + for pb.Next() { + Read(buf) + } + }) +} diff --git a/crypto/internal/fips140/ecdh/cast.go b/crypto/internal/fips140/ecdh/cast.go new file mode 100644 index 00000000000..cf728c3489e --- /dev/null +++ b/crypto/internal/fips140/ecdh/cast.go @@ -0,0 +1,54 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdh + +import ( + "bytes" + "errors" + "sync" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +var fipsSelfTest = sync.OnceFunc(func() { + // Per IG D.F, Scenario 2, path (1). + fips140.CAST("KAS-ECC-SSC P-256", func() error { + privateKey := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + publicKey := []byte{ + 0x04, + 0x51, 0x5c, 0x3d, 0x6e, 0xb9, 0xe3, 0x96, 0xb9, + 0x04, 0xd3, 0xfe, 0xca, 0x7f, 0x54, 0xfd, 0xcd, + 0x0c, 0xc1, 0xe9, 0x97, 0xbf, 0x37, 0x5d, 0xca, + 0x51, 0x5a, 0xd0, 0xa6, 0xc3, 0xb4, 0x03, 0x5f, + 0x45, 0x36, 0xbe, 0x3a, 0x50, 0xf3, 0x18, 0xfb, + 0xf9, 0xa5, 0x47, 0x59, 0x02, 0xa2, 0x21, 0x50, + 0x2b, 0xef, 0x0d, 0x57, 0xe0, 0x8c, 0x53, 0xb2, + 0xcc, 0x0a, 0x56, 0xf1, 0x7d, 0x9f, 0x93, 0x54, + } + want := []byte{ + 0xb4, 0xf1, 0xfc, 0xce, 0x40, 0x73, 0x5f, 0x83, + 0x6a, 0xf8, 0xd6, 0x31, 0x2d, 0x24, 0x8d, 0x1a, + 0x83, 0x48, 0x40, 0x56, 0x69, 0xa1, 0x95, 0xfa, + 0xc5, 0x35, 0x04, 0x06, 0xba, 0x76, 0xbc, 0xce, + } + k := &PrivateKey{d: privateKey, pub: PublicKey{curve: p256}} + peer := &PublicKey{curve: p256, q: publicKey} + got, err := ecdh(P256(), k, peer) + if err != nil { + return err + } + if !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +}) diff --git a/crypto/internal/fips140/ecdh/ecdh.go b/crypto/internal/fips140/ecdh/ecdh.go new file mode 100644 index 00000000000..94a684f47e5 --- /dev/null +++ b/crypto/internal/fips140/ecdh/ecdh.go @@ -0,0 +1,310 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdh + +import ( + "bytes" + "errors" + "io" + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// PrivateKey and PublicKey are not generic to make it possible to use them +// in other types without instantiating them with a specific point type. +// They are tied to one of the Curve types below through the curveID field. + +// All this is duplicated from crypto/internal/fips/ecdsa, but the standards are +// different and FIPS 140 does not allow reusing keys across them. + +type PrivateKey struct { + pub PublicKey + d []byte // bigmod.(*Nat).Bytes output (fixed length) +} + +func (priv *PrivateKey) Bytes() []byte { + return priv.d +} + +func (priv *PrivateKey) PublicKey() *PublicKey { + return &priv.pub +} + +type PublicKey struct { + curve curveID + q []byte // uncompressed nistec Point.Bytes output +} + +func (pub *PublicKey) Bytes() []byte { + return pub.q +} + +type curveID string + +const ( + p224 curveID = "P-224" + p256 curveID = "P-256" + p384 curveID = "P-384" + p521 curveID = "P-521" +) + +type Curve[P Point[P]] struct { + curve curveID + newPoint func() P + N []byte +} + +// Point is a generic constraint for the [nistec] Point types. +type Point[P any] interface { + *nistec.P224Point | *nistec.P256Point | *nistec.P384Point | *nistec.P521Point + Bytes() []byte + BytesX() ([]byte, error) + SetBytes([]byte) (P, error) + ScalarMult(P, []byte) (P, error) + ScalarBaseMult([]byte) (P, error) +} + +func P224() *Curve[*nistec.P224Point] { + return &Curve[*nistec.P224Point]{ + curve: p224, + newPoint: nistec.NewP224Point, + N: p224Order, + } +} + +var p224Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3d, +} + +func P256() *Curve[*nistec.P256Point] { + return &Curve[*nistec.P256Point]{ + curve: p256, + newPoint: nistec.NewP256Point, + N: p256Order, + } +} + +var p256Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, + 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, +} + +func P384() *Curve[*nistec.P384Point] { + return &Curve[*nistec.P384Point]{ + curve: p384, + newPoint: nistec.NewP384Point, + N: p384Order, + } +} + +var p384Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, + 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, + 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73, +} + +func P521() *Curve[*nistec.P521Point] { + return &Curve[*nistec.P521Point]{ + curve: p521, + newPoint: nistec.NewP521Point, + N: p521Order, + } +} + +var p521Order = []byte{0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, + 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, +} + +// GenerateKey generates a new ECDSA private key pair for the specified curve. +func GenerateKey[P Point[P]](c *Curve[P], rand io.Reader) (*PrivateKey, error) { + fips140.RecordApproved() + // This procedure is equivalent to Key Pair Generation by Testing + // Candidates, specified in NIST SP 800-56A Rev. 3, Section 5.6.1.2.2. + + for { + key := make([]byte, len(c.N)) + if err := drbg.ReadWithReader(rand, key); err != nil { + return nil, err + } + // In tests, rand will return all zeros and NewPrivateKey will reject + // the zero key as it generates the identity as a public key. This also + // makes this function consistent with crypto/elliptic.GenerateKey. + key[1] ^= 0x42 + + // Mask off any excess bits if the size of the underlying field is not a + // whole number of bytes, which is only the case for P-521. + if c.curve == p521 && c.N[0]&0b1111_1110 == 0 { + key[0] &= 0b0000_0001 + } + + privateKey, err := NewPrivateKey(c, key) + if err != nil { + continue + } + return privateKey, nil + } +} + +func NewPrivateKey[P Point[P]](c *Curve[P], key []byte) (*PrivateKey, error) { + // SP 800-56A Rev. 3, Section 5.6.1.2.2 checks that c <= n – 2 and then + // returns d = c + 1. Note that it follows that 0 < d < n. Equivalently, + // we check that 0 < d < n, and return d. + if len(key) != len(c.N) || isZero(key) || !isLess(key, c.N) { + return nil, errors.New("crypto/ecdh: invalid private key") + } + + p, err := c.newPoint().ScalarBaseMult(key) + if err != nil { + // This is unreachable because the only error condition of + // ScalarBaseMult is if the input is not the right size. + panic("crypto/ecdh: internal error: nistec ScalarBaseMult failed for a fixed-size input") + } + + publicKey := p.Bytes() + if len(publicKey) == 1 { + // The encoding of the identity is a single 0x00 byte. This is + // unreachable because the only scalar that generates the identity is + // zero, which is rejected above. + panic("crypto/ecdh: internal error: public key is the identity element") + } + + // A "Pairwise Consistency Test" makes no sense if we just generated the + // public key from an ephemeral private key. Moreover, there is no way to + // check it aside from redoing the exact same computation again. SP 800-56A + // Rev. 3, Section 5.6.2.1.4 acknowledges that, and doesn't require it. + // However, ISO 19790:2012, Section 7.10.3.3 has a blanket requirement for a + // PCT for all generated keys (AS10.35) and FIPS 140-3 IG 10.3.A, Additional + // Comment 1 goes out of its way to say that "the PCT shall be performed + // consistent [...], even if the underlying standard does not require a + // PCT". So we do it. And make ECDH nearly 50% slower (only) in FIPS mode. + if err := fips140.PCT("ECDH PCT", func() error { + p1, err := c.newPoint().ScalarBaseMult(key) + if err != nil { + return err + } + if !bytes.Equal(p1.Bytes(), publicKey) { + return errors.New("crypto/ecdh: public key does not match private key") + } + return nil + }); err != nil { + panic(err) + } + + k := &PrivateKey{d: bytes.Clone(key), pub: PublicKey{curve: c.curve, q: publicKey}} + return k, nil +} + +func NewPublicKey[P Point[P]](c *Curve[P], key []byte) (*PublicKey, error) { + // Reject the point at infinity and compressed encodings. + if len(key) == 0 || key[0] != 4 { + return nil, errors.New("crypto/ecdh: invalid public key") + } + + // SetBytes checks that x and y are in the interval [0, p - 1], and that + // the point is on the curve. Along with the rejection of the point at + // infinity (the identity element) above, this fulfills the requirements + // of NIST SP 800-56A Rev. 3, Section 5.6.2.3.4. + if _, err := c.newPoint().SetBytes(key); err != nil { + return nil, err + } + + return &PublicKey{curve: c.curve, q: bytes.Clone(key)}, nil +} + +func ECDH[P Point[P]](c *Curve[P], k *PrivateKey, peer *PublicKey) ([]byte, error) { + fipsSelfTest() + fips140.RecordApproved() + return ecdh(c, k, peer) +} + +func ecdh[P Point[P]](c *Curve[P], k *PrivateKey, peer *PublicKey) ([]byte, error) { + if c.curve != k.pub.curve { + return nil, errors.New("crypto/ecdh: mismatched curves") + } + if k.pub.curve != peer.curve { + return nil, errors.New("crypto/ecdh: mismatched curves") + } + + // This applies the Shared Secret Computation of the Ephemeral Unified Model + // scheme specified in NIST SP 800-56A Rev. 3, Section 6.1.2.2. + + // Per Section 5.6.2.3.4, Step 1, reject the identity element (0x00). + if len(k.pub.q) == 1 { + return nil, errors.New("crypto/ecdh: public key is the identity element") + } + + // SetBytes checks that (x, y) are reduced modulo p, and that they are on + // the curve, performing Steps 2-3 of Section 5.6.2.3.4. + p, err := c.newPoint().SetBytes(peer.q) + if err != nil { + return nil, err + } + + // Compute P according to Section 5.7.1.2. + if _, err := p.ScalarMult(p, k.d); err != nil { + return nil, err + } + + // BytesX checks that the result is not the identity element, and returns the + // x-coordinate of the result, performing Steps 2-5 of Section 5.7.1.2. + return p.BytesX() +} + +// isZero reports whether x is all zeroes in constant time. +func isZero(x []byte) bool { + var acc byte + for _, b := range x { + acc |= b + } + return acc == 0 +} + +// isLess reports whether a < b, where a and b are big-endian buffers of the +// same length and shorter than 72 bytes. +func isLess(a, b []byte) bool { + if len(a) != len(b) { + panic("crypto/ecdh: internal error: mismatched isLess inputs") + } + + // Copy the values into a fixed-size preallocated little-endian buffer. + // 72 bytes is enough for every scalar in this package, and having a fixed + // size lets us avoid heap allocations. + if len(a) > 72 { + panic("crypto/ecdh: internal error: isLess input too large") + } + bufA, bufB := make([]byte, 72), make([]byte, 72) + for i := range a { + bufA[i], bufB[i] = a[len(a)-i-1], b[len(b)-i-1] + } + + // Perform a subtraction with borrow. + var borrow uint64 + for i := 0; i < len(bufA); i += 8 { + limbA, limbB := byteorder.LEUint64(bufA[i:]), byteorder.LEUint64(bufB[i:]) + _, borrow = bits.Sub64(limbA, limbB, borrow) + } + + // If there is a borrow at the end of the operation, then a < b. + return borrow == 1 +} diff --git a/crypto/internal/fips140/ecdh/order_test.go b/crypto/internal/fips140/ecdh/order_test.go new file mode 100644 index 00000000000..c8aee9d7114 --- /dev/null +++ b/crypto/internal/fips140/ecdh/order_test.go @@ -0,0 +1,27 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdh + +import ( + "bytes" + "testing" + + "github.com/runZeroInc/excrypto/crypto/elliptic" +) + +func TestOrders(t *testing.T) { + if !bytes.Equal(elliptic.P224().Params().N.Bytes(), P224().N) { + t.Errorf("P-224 order mismatch") + } + if !bytes.Equal(elliptic.P256().Params().N.Bytes(), P256().N) { + t.Errorf("P-256 order mismatch") + } + if !bytes.Equal(elliptic.P384().Params().N.Bytes(), P384().N) { + t.Errorf("P-384 order mismatch") + } + if !bytes.Equal(elliptic.P521().Params().N.Bytes(), P521().N) { + t.Errorf("P-521 order mismatch") + } +} diff --git a/crypto/internal/fips140/ecdsa/cast.go b/crypto/internal/fips140/ecdsa/cast.go new file mode 100644 index 00000000000..a2319ff5fd5 --- /dev/null +++ b/crypto/internal/fips140/ecdsa/cast.go @@ -0,0 +1,138 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "bytes" + "errors" + "sync" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" +) + +func testPrivateKey() *PrivateKey { + // https://www.rfc-editor.org/rfc/rfc9500.html#section-2.3 + return &PrivateKey{ + pub: PublicKey{ + curve: p256, + q: []byte{ + 0x04, + 0x42, 0x25, 0x48, 0xF8, 0x8F, 0xB7, 0x82, 0xFF, + 0xB5, 0xEC, 0xA3, 0x74, 0x44, 0x52, 0xC7, 0x2A, + 0x1E, 0x55, 0x8F, 0xBD, 0x6F, 0x73, 0xBE, 0x5E, + 0x48, 0xE9, 0x32, 0x32, 0xCC, 0x45, 0xC5, 0xB1, + 0x6C, 0x4C, 0xD1, 0x0C, 0x4C, 0xB8, 0xD5, 0xB8, + 0xA1, 0x71, 0x39, 0xE9, 0x48, 0x82, 0xC8, 0x99, + 0x25, 0x72, 0x99, 0x34, 0x25, 0xF4, 0x14, 0x19, + 0xAB, 0x7E, 0x90, 0xA4, 0x2A, 0x49, 0x42, 0x72}, + }, + d: []byte{ + 0xE6, 0xCB, 0x5B, 0xDD, 0x80, 0xAA, 0x45, 0xAE, + 0x9C, 0x95, 0xE8, 0xC1, 0x54, 0x76, 0x67, 0x9F, + 0xFE, 0xC9, 0x53, 0xC1, 0x68, 0x51, 0xE7, 0x11, + 0xE7, 0x43, 0x93, 0x95, 0x89, 0xC6, 0x4F, 0xC1, + }, + } +} + +func testHash() []byte { + return []byte{ + 0x17, 0x1b, 0x1f, 0x5e, 0x9f, 0x8f, 0x8c, 0x5c, + 0x42, 0xe8, 0x06, 0x59, 0x7b, 0x54, 0xc7, 0xb4, + 0x49, 0x05, 0xa1, 0xdb, 0x3a, 0x3c, 0x31, 0xd3, + 0xb7, 0x56, 0x45, 0x8c, 0xc2, 0xd6, 0x88, 0x62, + 0x9e, 0xd6, 0x7b, 0x9b, 0x25, 0x68, 0xd6, 0xc6, + 0x18, 0x94, 0x1e, 0xfe, 0xe3, 0x33, 0x78, 0xa6, + 0xe1, 0xce, 0x13, 0x88, 0x81, 0x26, 0x02, 0x52, + 0xdf, 0xc2, 0x0a, 0xf2, 0x67, 0x49, 0x0a, 0x20, + } +} + +func fipsPCT[P Point[P]](c *Curve[P], k *PrivateKey) error { + return fips140.PCT("ECDSA PCT", func() error { + hash := testHash() + drbg := newDRBG(sha512.New, k.d, bits2octets(P256(), hash), nil) + sig, err := sign(c, k, drbg, hash) + if err != nil { + return err + } + return Verify(c, &k.pub, hash, sig) + }) +} + +var fipsSelfTest = sync.OnceFunc(func() { + fips140.CAST("ECDSA P-256 SHA2-512 sign and verify", func() error { + k := testPrivateKey() + Z := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + persStr := []byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + hash := testHash() + want := &Signature{ + R: []byte{ + 0x33, 0x64, 0x96, 0xff, 0x8a, 0xfe, 0xaa, 0x0b, + 0x2c, 0x4a, 0x1a, 0x97, 0x77, 0xcc, 0x84, 0xa5, + 0x7e, 0x88, 0x1f, 0x16, 0x2d, 0xe0, 0x29, 0xf7, + 0x62, 0xc2, 0x34, 0x18, 0x10, 0x9c, 0x69, 0x8a, + }, S: []byte{ + 0x97, 0x53, 0x2e, 0x13, 0x6e, 0xd0, 0x9b, 0x30, + 0x8a, 0xdf, 0x4f, 0xe0, 0x54, 0x82, 0x14, 0x83, + 0x5e, 0x93, 0xc7, 0x79, 0x4b, 0x18, 0xa3, 0xf1, + 0x8a, 0x60, 0xae, 0x52, 0x31, 0xe4, 0x2e, 0x4e, + }, + } + drbg := newDRBG(sha512.New, Z, nil, plainPersonalizationString(persStr)) + got, err := sign(P256(), k, drbg, hash) + if err != nil { + return err + } + if err := verify(P256(), &k.pub, hash, got); err != nil { + return err + } + if !bytes.Equal(got.R, want.R) || !bytes.Equal(got.S, want.S) { + return errors.New("unexpected result") + } + return nil + }) +}) + +var fipsSelfTestDeterministic = sync.OnceFunc(func() { + fips140.CAST("DetECDSA P-256 SHA2-512 sign", func() error { + k := testPrivateKey() + hash := testHash() + want := &Signature{ + R: []byte{ + 0x9f, 0xc3, 0x83, 0x32, 0x6e, 0xd9, 0x4f, 0x8e, + 0x24, 0xa0, 0x19, 0xef, 0x1d, 0x3a, 0xc3, 0x55, + 0xdd, 0x4b, 0x98, 0xae, 0x78, 0xa7, 0xaf, 0xd3, + 0xfd, 0xf3, 0x22, 0x1c, 0x8b, 0xd6, 0x11, 0x7b, + }, S: []byte{ + 0xd6, 0x52, 0x87, 0x41, 0x71, 0xbd, 0x66, 0xd1, + 0xaf, 0x6c, 0x61, 0xdd, 0xd8, 0xa7, 0xbb, 0xd2, + 0xf7, 0xd5, 0x47, 0x70, 0xe9, 0xe4, 0xac, 0x0a, + 0xb9, 0xfa, 0x0f, 0xbd, 0x3b, 0x9b, 0xc2, 0xfe, + }, + } + drbg := newDRBG(sha512.New, k.d, bits2octets(P256(), hash), nil) + got, err := sign(P256(), k, drbg, hash) + if err != nil { + return err + } + if err := verify(P256(), &k.pub, hash, got); err != nil { + return err + } + if !bytes.Equal(got.R, want.R) || !bytes.Equal(got.S, want.S) { + return errors.New("unexpected result") + } + return nil + }) +}) diff --git a/crypto/internal/fips140/ecdsa/ecdsa.go b/crypto/internal/fips140/ecdsa/ecdsa.go new file mode 100644 index 00000000000..90b850b8cab --- /dev/null +++ b/crypto/internal/fips140/ecdsa/ecdsa.go @@ -0,0 +1,506 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "bytes" + "errors" + "io" + "sync" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec" +) + +// PrivateKey and PublicKey are not generic to make it possible to use them +// in other types without instantiating them with a specific point type. +// They are tied to one of the Curve types below through the curveID field. + +type PrivateKey struct { + pub PublicKey + d []byte // bigmod.(*Nat).Bytes output (same length as the curve order) +} + +func (priv *PrivateKey) Bytes() []byte { + return priv.d +} + +func (priv *PrivateKey) PublicKey() *PublicKey { + return &priv.pub +} + +type PublicKey struct { + curve curveID + q []byte // uncompressed nistec Point.Bytes output +} + +func (pub *PublicKey) Bytes() []byte { + return pub.q +} + +type curveID string + +const ( + p224 curveID = "P-224" + p256 curveID = "P-256" + p384 curveID = "P-384" + p521 curveID = "P-521" +) + +type Curve[P Point[P]] struct { + curve curveID + newPoint func() P + ordInverse func([]byte) ([]byte, error) + N *bigmod.Modulus + nMinus2 []byte +} + +// Point is a generic constraint for the [nistec] Point types. +type Point[P any] interface { + *nistec.P224Point | *nistec.P256Point | *nistec.P384Point | *nistec.P521Point + Bytes() []byte + BytesX() ([]byte, error) + SetBytes([]byte) (P, error) + ScalarMult(P, []byte) (P, error) + ScalarBaseMult([]byte) (P, error) + Add(p1, p2 P) P +} + +func precomputeParams[P Point[P]](c *Curve[P], order []byte) { + var err error + c.N, err = bigmod.NewModulus(order) + if err != nil { + panic(err) + } + two, _ := bigmod.NewNat().SetBytes([]byte{2}, c.N) + c.nMinus2 = bigmod.NewNat().ExpandFor(c.N).Sub(two, c.N).Bytes(c.N) +} + +func P224() *Curve[*nistec.P224Point] { return _P224() } + +var _P224 = sync.OnceValue(func() *Curve[*nistec.P224Point] { + c := &Curve[*nistec.P224Point]{ + curve: p224, + newPoint: nistec.NewP224Point, + } + precomputeParams(c, p224Order) + return c +}) + +var p224Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3d, +} + +func P256() *Curve[*nistec.P256Point] { return _P256() } + +var _P256 = sync.OnceValue(func() *Curve[*nistec.P256Point] { + c := &Curve[*nistec.P256Point]{ + curve: p256, + newPoint: nistec.NewP256Point, + ordInverse: nistec.P256OrdInverse, + } + precomputeParams(c, p256Order) + return c +}) + +var p256Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, + 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51} + +func P384() *Curve[*nistec.P384Point] { return _P384() } + +var _P384 = sync.OnceValue(func() *Curve[*nistec.P384Point] { + c := &Curve[*nistec.P384Point]{ + curve: p384, + newPoint: nistec.NewP384Point, + } + precomputeParams(c, p384Order) + return c +}) + +var p384Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, + 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, + 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73} + +func P521() *Curve[*nistec.P521Point] { return _P521() } + +var _P521 = sync.OnceValue(func() *Curve[*nistec.P521Point] { + c := &Curve[*nistec.P521Point]{ + curve: p521, + newPoint: nistec.NewP521Point, + } + precomputeParams(c, p521Order) + return c +}) + +var p521Order = []byte{0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, + 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09} + +func NewPrivateKey[P Point[P]](c *Curve[P], D, Q []byte) (*PrivateKey, error) { + fips140.RecordApproved() + pub, err := NewPublicKey(c, Q) + if err != nil { + return nil, err + } + d, err := bigmod.NewNat().SetBytes(D, c.N) + if err != nil { + return nil, err + } + priv := &PrivateKey{pub: *pub, d: d.Bytes(c.N)} + if err := fipsPCT(c, priv); err != nil { + // This can happen if the application went out of its way to make an + // ecdsa.PrivateKey with a mismatching PublicKey. + return nil, err + } + return priv, nil +} + +func NewPublicKey[P Point[P]](c *Curve[P], Q []byte) (*PublicKey, error) { + // SetBytes checks that Q is a valid point on the curve, and that its + // coordinates are reduced modulo p, fulfilling the requirements of SP + // 800-89, Section 5.3.2. + _, err := c.newPoint().SetBytes(Q) + if err != nil { + return nil, err + } + return &PublicKey{curve: c.curve, q: Q}, nil +} + +// GenerateKey generates a new ECDSA private key pair for the specified curve. +func GenerateKey[P Point[P]](c *Curve[P], rand io.Reader) (*PrivateKey, error) { + fips140.RecordApproved() + + k, Q, err := randomPoint(c, func(b []byte) error { + return drbg.ReadWithReader(rand, b) + }) + if err != nil { + return nil, err + } + + priv := &PrivateKey{ + pub: PublicKey{ + curve: c.curve, + q: Q.Bytes(), + }, + d: k.Bytes(c.N), + } + if err := fipsPCT(c, priv); err != nil { + // This clearly can't happen, but FIPS 140-3 mandates that we check it. + panic(err) + } + return priv, nil +} + +// randomPoint returns a random scalar and the corresponding point using a +// procedure equivalent to FIPS 186-5, Appendix A.2.2 (ECDSA Key Pair Generation +// by Rejection Sampling) and to Appendix A.3.2 (Per-Message Secret Number +// Generation of Private Keys by Rejection Sampling) or Appendix A.3.3 +// (Per-Message Secret Number Generation for Deterministic ECDSA) followed by +// Step 5 of Section 6.4.1. +func randomPoint[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmod.Nat, p P, err error) { + for { + b := make([]byte, c.N.Size()) + if err := generate(b); err != nil { + return nil, nil, err + } + + // Take only the leftmost bits of the generated random value. This is + // both necessary to increase the chance of the random value being in + // the correct range and to match the specification. It's unfortunate + // that we need to do a shift instead of a mask, but see the comment on + // rightShift. + // + // These are the most dangerous lines in the package and maybe in the + // library: a single bit of bias in the selection of nonces would likely + // lead to key recovery, but no tests would fail. Look but DO NOT TOUCH. + if excess := len(b)*8 - c.N.BitLen(); excess > 0 { + // Just to be safe, assert that this only happens for the one curve that + // doesn't have a round number of bits. + if c.curve != p521 { + panic("ecdsa: internal error: unexpectedly masking off bits") + } + b = rightShift(b, excess) + } + + // FIPS 186-5, Appendix A.4.2 makes us check x <= N - 2 and then return + // x + 1. Note that it follows that 0 < x + 1 < N. Instead, SetBytes + // checks that k < N, and we explicitly check 0 != k. Since k can't be + // negative, this is strictly equivalent. None of this matters anyway + // because the chance of selecting zero is cryptographically negligible. + if k, err := bigmod.NewNat().SetBytes(b, c.N); err == nil && k.IsZero() == 0 { + p, err := c.newPoint().ScalarBaseMult(k.Bytes(c.N)) + return k, p, err + } + + if testingOnlyRejectionSamplingLooped != nil { + testingOnlyRejectionSamplingLooped() + } + } +} + +// testingOnlyRejectionSamplingLooped is called when rejection sampling in +// randomPoint rejects a candidate for being higher than the modulus. +var testingOnlyRejectionSamplingLooped func() + +// Signature is an ECDSA signature, where r and s are represented as big-endian +// byte slices of the same length as the curve order. +type Signature struct { + R, S []byte +} + +// Sign signs a hash (which shall be the result of hashing a larger message with +// the hash function H) using the private key, priv. If the hash is longer than +// the bit-length of the private key's curve order, the hash will be truncated +// to that length. +func Sign[P Point[P], H hash.Hash](c *Curve[P], h func() H, priv *PrivateKey, rand io.Reader, hash []byte) (*Signature, error) { + if priv.pub.curve != c.curve { + return nil, errors.New("ecdsa: private key does not match curve") + } + fips140.RecordApproved() + fipsSelfTest() + + // Random ECDSA is dangerous, because a failure of the RNG would immediately + // leak the private key. Instead, we use a "hedged" approach, as specified + // in draft-irtf-cfrg-det-sigs-with-noise-04, Section 4. This has also the + // advantage of closely resembling Deterministic ECDSA. + + Z := make([]byte, len(priv.d)) + if err := drbg.ReadWithReader(rand, Z); err != nil { + return nil, err + } + + // See https://github.com/cfrg/draft-irtf-cfrg-det-sigs-with-noise/issues/6 + // for the FIPS compliance of this method. In short Z is entropy from the + // main DRBG, of length 3/2 of security_strength, so the nonce is optional + // per SP 800-90Ar1, Section 8.6.7, and the rest is a personalization + // string, which per SP 800-90Ar1, Section 8.7.1 may contain secret + // information. + drbg := newDRBG(h, Z, nil, blockAlignedPersonalizationString{priv.d, bits2octets(c, hash)}) + + return sign(c, priv, drbg, hash) +} + +// SignDeterministic signs a hash (which shall be the result of hashing a +// larger message with the hash function H) using the private key, priv. If the +// hash is longer than the bit-length of the private key's curve order, the hash +// will be truncated to that length. This applies Deterministic ECDSA as +// specified in FIPS 186-5 and RFC 6979. +func SignDeterministic[P Point[P], H hash.Hash](c *Curve[P], h func() H, priv *PrivateKey, hash []byte) (*Signature, error) { + if priv.pub.curve != c.curve { + return nil, errors.New("ecdsa: private key does not match curve") + } + fips140.RecordApproved() + fipsSelfTestDeterministic() + drbg := newDRBG(h, priv.d, bits2octets(c, hash), nil) // RFC 6979, Section 3.3 + return sign(c, priv, drbg, hash) +} + +// bits2octets as specified in FIPS 186-5, Appendix B.2.4 or RFC 6979, +// Section 2.3.4. See RFC 6979, Section 3.5 for the rationale. +func bits2octets[P Point[P]](c *Curve[P], hash []byte) []byte { + e := bigmod.NewNat() + hashToNat(c, e, hash) + return e.Bytes(c.N) +} + +func signGeneric[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { + // FIPS 186-5, Section 6.4.1 + + k, R, err := randomPoint(c, func(b []byte) error { + drbg.Generate(b) + return nil + }) + if err != nil { + return nil, err + } + + // kInv = k⁻¹ + kInv := bigmod.NewNat() + inverse(c, kInv, k) + + Rx, err := R.BytesX() + if err != nil { + return nil, err + } + r, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) + if err != nil { + return nil, err + } + + // The spec wants us to retry here, but the chance of hitting this condition + // on a large prime-order group like the NIST curves we support is + // cryptographically negligible. If we hit it, something is awfully wrong. + if r.IsZero() == 1 { + return nil, errors.New("ecdsa: internal error: r is zero") + } + + e := bigmod.NewNat() + hashToNat(c, e, hash) + + s, err := bigmod.NewNat().SetBytes(priv.d, c.N) + if err != nil { + return nil, err + } + s.Mul(r, c.N) + s.Add(e, c.N) + s.Mul(kInv, c.N) + + // Again, the chance of this happening is cryptographically negligible. + if s.IsZero() == 1 { + return nil, errors.New("ecdsa: internal error: s is zero") + } + + return &Signature{r.Bytes(c.N), s.Bytes(c.N)}, nil +} + +// inverse sets kInv to the inverse of k modulo the order of the curve. +func inverse[P Point[P]](c *Curve[P], kInv, k *bigmod.Nat) { + if c.ordInverse != nil { + kBytes, err := c.ordInverse(k.Bytes(c.N)) + // Some platforms don't implement ordInverse, and always return an error. + if err == nil { + _, err := kInv.SetBytes(kBytes, c.N) + if err != nil { + panic("ecdsa: internal error: ordInverse produced an invalid value") + } + return + } + } + + // Calculate the inverse of s in GF(N) using Fermat's method + // (exponentiation modulo P - 2, per Euler's theorem) + kInv.Exp(k, c.nMinus2, c.N) +} + +// hashToNat sets e to the left-most bits of hash, according to +// FIPS 186-5, Section 6.4.1, point 2 and Section 6.4.2, point 3. +func hashToNat[P Point[P]](c *Curve[P], e *bigmod.Nat, hash []byte) { + // ECDSA asks us to take the left-most log2(N) bits of hash, and use them as + // an integer modulo N. This is the absolute worst of all worlds: we still + // have to reduce, because the result might still overflow N, but to take + // the left-most bits for P-521 we have to do a right shift. + if size := c.N.Size(); len(hash) >= size { + hash = hash[:size] + if excess := len(hash)*8 - c.N.BitLen(); excess > 0 { + hash = rightShift(hash, excess) + } + } + _, err := e.SetOverflowingBytes(hash, c.N) + if err != nil { + panic("ecdsa: internal error: truncated hash is too long") + } +} + +// rightShift implements the right shift necessary for bits2int, which takes the +// leftmost bits of either the hash or HMAC_DRBG output. +// +// Note how taking the rightmost bits would have been as easy as masking the +// first byte, but we can't have nice things. +func rightShift(b []byte, shift int) []byte { + if shift <= 0 || shift >= 8 { + panic("ecdsa: internal error: shift can only be by 1 to 7 bits") + } + b = bytes.Clone(b) + for i := len(b) - 1; i >= 0; i-- { + b[i] >>= shift + if i > 0 { + b[i] |= b[i-1] << (8 - shift) + } + } + return b +} + +// Verify verifies the signature, sig, of hash (which should be the result of +// hashing a larger message) using the public key, pub. If the hash is longer +// than the bit-length of the private key's curve order, the hash will be +// truncated to that length. +// +// The inputs are not considered confidential, and may leak through timing side +// channels, or if an attacker has control of part of the inputs. +func Verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error { + if pub.curve != c.curve { + return errors.New("ecdsa: public key does not match curve") + } + fips140.RecordApproved() + fipsSelfTest() + return verify(c, pub, hash, sig) +} + +func verifyGeneric[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error { + // FIPS 186-5, Section 6.4.2 + + Q, err := c.newPoint().SetBytes(pub.q) + if err != nil { + return err + } + + r, err := bigmod.NewNat().SetBytes(sig.R, c.N) + if err != nil { + return err + } + if r.IsZero() == 1 { + return errors.New("ecdsa: invalid signature: r is zero") + } + s, err := bigmod.NewNat().SetBytes(sig.S, c.N) + if err != nil { + return err + } + if s.IsZero() == 1 { + return errors.New("ecdsa: invalid signature: s is zero") + } + + e := bigmod.NewNat() + hashToNat(c, e, hash) + + // w = s⁻¹ + w := bigmod.NewNat() + inverse(c, w, s) + + // p₁ = [e * s⁻¹]G + p1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N)) + if err != nil { + return err + } + // p₂ = [r * s⁻¹]Q + p2, err := Q.ScalarMult(Q, w.Mul(r, c.N).Bytes(c.N)) + if err != nil { + return err + } + // BytesX returns an error for the point at infinity. + Rx, err := p1.Add(p1, p2).BytesX() + if err != nil { + return err + } + + v, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) + if err != nil { + return err + } + + if v.Equal(r) != 1 { + return errors.New("ecdsa: signature did not verify") + } + return nil +} diff --git a/crypto/internal/fips140/ecdsa/ecdsa_noasm.go b/crypto/internal/fips140/ecdsa/ecdsa_noasm.go new file mode 100644 index 00000000000..ffcc9fa0884 --- /dev/null +++ b/crypto/internal/fips140/ecdsa/ecdsa_noasm.go @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !s390x || purego + +package ecdsa + +func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { + return signGeneric(c, priv, drbg, hash) +} + +func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error { + return verifyGeneric(c, pub, hash, sig) +} diff --git a/crypto/ecdsa/ecdsa_s390x.go b/crypto/internal/fips140/ecdsa/ecdsa_s390x.go similarity index 53% rename from crypto/ecdsa/ecdsa_s390x.go rename to crypto/internal/fips140/ecdsa/ecdsa_s390x.go index 6c59c144d71..783dbf479f9 100644 --- a/crypto/ecdsa/ecdsa_s390x.go +++ b/crypto/internal/fips140/ecdsa/ecdsa_s390x.go @@ -8,10 +8,10 @@ package ecdsa import ( "errors" - "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/internal/cpu" - "io" - "math/big" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" ) // kdsa invokes the "compute digital signature authentication" @@ -25,62 +25,88 @@ import ( //go:noescape func kdsa(fc uint64, params *[4096]byte) (errn uint64) -// testingDisableKDSA forces the generic fallback path. It must only be set in tests. -var testingDisableKDSA bool +var supportsKDSA = cpu.S390XHasECDSA + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf + impl.Register("ecdsa", "CPACF", &supportsKDSA) +} // canUseKDSA checks if KDSA instruction is available, and if it is, it checks // the name of the curve to see if it matches the curves supported(P-256, P-384, P-521). // Then, based on the curve name, a function code and a block size will be assigned. // If KDSA instruction is not available or if the curve is not supported, canUseKDSA // will set ok to false. -func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) { - if testingDisableKDSA { - return 0, 0, false - } - if !cpu.S390X.HasECDSA { +func canUseKDSA(c curveID) (functionCode uint64, blockSize int, ok bool) { + if !supportsKDSA { return 0, 0, false } - switch c.Params().Name { - case "P-256": + switch c { + case p256: return 1, 32, true - case "P-384": + case p384: return 2, 48, true - case "P-521": + case p521: + // Note that the block size doesn't match the field size for P-521. return 3, 80, true } return 0, 0, false // A mismatch } -func hashToBytes(dst, hash []byte, c elliptic.Curve) { - l := len(dst) - if n := c.Params().N.BitLen(); n == l*8 { - // allocation free path for curves with a length that is a whole number of bytes - if len(hash) >= l { - // truncate hash - copy(dst, hash[:l]) - return +func hashToBytes[P Point[P]](c *Curve[P], hash []byte) []byte { + e := bigmod.NewNat() + hashToNat(c, e, hash) + return e.Bytes(c.N) +} + +// randomScalar is a copy of [randomPoint] that doesn't call ScalarBaseMult. +func randomScalar[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmod.Nat, err error) { + for { + b := make([]byte, c.N.Size()) + if err := generate(b); err != nil { + return nil, err } - // pad hash with leading zeros - p := l - len(hash) - for i := 0; i < p; i++ { - dst[i] = 0 + if excess := len(b)*8 - c.N.BitLen(); excess > 0 { + if c.curve != p521 { + panic("ecdsa: internal error: unexpectedly masking off bits") + } + b = rightShift(b, excess) + } + if k, err := bigmod.NewNat().SetBytes(b, c.N); err == nil && k.IsZero() == 0 { + return k, nil } - copy(dst[p:], hash) - return } - // TODO(mundaym): avoid hashToInt call here - hashToInt(hash, c).FillBytes(dst) } -func signAsm(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { - c := priv.Curve - functionCode, blockSize, ok := canUseKDSA(c) +func appendBlock(p []byte, blocksize int, b []byte) []byte { + if len(b) > blocksize { + panic("ecdsa: internal error: appendBlock input larger than block") + } + padding := blocksize - len(b) + p = append(p, make([]byte, padding)...) + return append(p, b...) +} + +func trimBlock(p []byte, size int) ([]byte, error) { + for _, b := range p[:len(p)-size] { + if b != 0 { + return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature") + } + } + return p[len(p)-size:], nil +} + +func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { + functionCode, blockSize, ok := canUseKDSA(c.curve) if !ok { - return nil, errNoAsm + return signGeneric(c, priv, drbg, hash) } for { - var k *big.Int - k, err = randFieldElement(c, csprng) + k, err := randomScalar(c, func(b []byte) error { + drbg.Generate(b) + return nil + }) if err != nil { return nil, err } @@ -108,37 +134,42 @@ func signAsm(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err e // Copy content into the parameter block. In the sign case, // we copy hashed message, private key and random number into - // the parameter block. - hashToBytes(params[2*blockSize:3*blockSize], hash, c) - priv.D.FillBytes(params[3*blockSize : 4*blockSize]) - k.FillBytes(params[4*blockSize : 5*blockSize]) + // the parameter block. We skip the signature slots. + p := params[:2*blockSize] + p = appendBlock(p, blockSize, hashToBytes(c, hash)) + p = appendBlock(p, blockSize, priv.d) + p = appendBlock(p, blockSize, k.Bytes(c.N)) // Convert verify function code into a sign function code by adding 8. // We also need to set the 'deterministic' bit in the function code, by // adding 128, in order to stop the instruction using its own random number // generator in addition to the random number we supply. switch kdsa(functionCode+136, ¶ms) { case 0: // success - return encodeSignature(params[:blockSize], params[blockSize:2*blockSize]) + elementSize := (c.N.BitLen() + 7) / 8 + r, err := trimBlock(params[:blockSize], elementSize) + if err != nil { + return nil, err + } + s, err := trimBlock(params[blockSize:2*blockSize], elementSize) + if err != nil { + return nil, err + } + return &Signature{R: r, S: s}, nil case 1: // error - return nil, errZeroParam + return nil, errors.New("zero parameter") case 2: // retry continue } - panic("unreachable") } } -func verifyAsm(pub *PublicKey, hash []byte, sig []byte) error { - c := pub.Curve - functionCode, blockSize, ok := canUseKDSA(c) +func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error { + functionCode, blockSize, ok := canUseKDSA(c.curve) if !ok { - return errNoAsm + return verifyGeneric(c, pub, hash, sig) } - r, s, err := parseSignature(sig) - if err != nil { - return err - } + r, s := sig.R, sig.S if len(r) > blockSize || len(s) > blockSize { return errors.New("invalid signature") } @@ -167,11 +198,12 @@ func verifyAsm(pub *PublicKey, hash []byte, sig []byte) error { // Copy content into the parameter block. In the verify case, // we copy signature (r), signature(s), hashed message, public key x component, // and public key y component into the parameter block. - copy(params[0*blockSize+blockSize-len(r):], r) - copy(params[1*blockSize+blockSize-len(s):], s) - hashToBytes(params[2*blockSize:3*blockSize], hash, c) - pub.X.FillBytes(params[3*blockSize : 4*blockSize]) - pub.Y.FillBytes(params[4*blockSize : 5*blockSize]) + p := params[:0] + p = appendBlock(p, blockSize, r) + p = appendBlock(p, blockSize, s) + p = appendBlock(p, blockSize, hashToBytes(c, hash)) + p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2]) + p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:]) if kdsa(functionCode, ¶ms) != 0 { return errors.New("invalid signature") } diff --git a/crypto/ecdsa/ecdsa_s390x.s b/crypto/internal/fips140/ecdsa/ecdsa_s390x.s similarity index 100% rename from crypto/ecdsa/ecdsa_s390x.s rename to crypto/internal/fips140/ecdsa/ecdsa_s390x.s diff --git a/crypto/internal/fips140/ecdsa/ecdsa_test.go b/crypto/internal/fips140/ecdsa/ecdsa_test.go new file mode 100644 index 00000000000..4707277b159 --- /dev/null +++ b/crypto/internal/fips140/ecdsa/ecdsa_test.go @@ -0,0 +1,98 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "bytes" + "io" + "testing" + + "crypto/rand" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" +) + +func TestRandomPoint(t *testing.T) { + t.Run("P-224", func(t *testing.T) { testRandomPoint(t, P224()) }) + t.Run("P-256", func(t *testing.T) { testRandomPoint(t, P256()) }) + t.Run("P-384", func(t *testing.T) { testRandomPoint(t, P384()) }) + t.Run("P-521", func(t *testing.T) { testRandomPoint(t, P521()) }) +} + +func testRandomPoint[P Point[P]](t *testing.T, c *Curve[P]) { + t.Cleanup(func() { testingOnlyRejectionSamplingLooped = nil }) + var loopCount int + testingOnlyRejectionSamplingLooped = func() { loopCount++ } + + // A sequence of all ones will generate 2^N-1, which should be rejected. + // (Unless, for example, we are masking too many bits.) + r := io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0xff}, 100)), rand.Reader) + if k, p, err := randomPoint(c, func(b []byte) error { + _, err := r.Read(b) + return err + }); err != nil { + t.Fatal(err) + } else if k.IsZero() == 1 { + t.Error("k is zero") + } else if p.Bytes()[0] != 4 { + t.Error("p is infinity") + } + if loopCount == 0 { + t.Error("overflow was not rejected") + } + loopCount = 0 + + // A sequence of all zeroes will generate zero, which should be rejected. + r = io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0}, 100)), rand.Reader) + if k, p, err := randomPoint(c, func(b []byte) error { + _, err := r.Read(b) + return err + }); err != nil { + t.Fatal(err) + } else if k.IsZero() == 1 { + t.Error("k is zero") + } else if p.Bytes()[0] != 4 { + t.Error("p is infinity") + } + if loopCount == 0 { + t.Error("zero was not rejected") + } + loopCount = 0 + + // P-256 has a 2⁻³² chance of randomly hitting a rejection. For P-224 it's + // 2⁻¹¹², for P-384 it's 2⁻¹⁹⁴, and for P-521 it's 2⁻²⁶², so if we hit in + // tests, something is horribly wrong. (For example, we are masking the + // wrong bits.) + if c.curve == p256 { + return + } + if k, p, err := randomPoint(c, func(b []byte) error { + _, err := rand.Reader.Read(b) + return err + }); err != nil { + t.Fatal(err) + } else if k.IsZero() == 1 { + t.Error("k is zero") + } else if p.Bytes()[0] != 4 { + t.Error("p is infinity") + } + if loopCount > 0 { + t.Error("unexpected rejection") + } +} + +func TestHashToNat(t *testing.T) { + t.Run("P-224", func(t *testing.T) { testHashToNat(t, P224()) }) + t.Run("P-256", func(t *testing.T) { testHashToNat(t, P256()) }) + t.Run("P-384", func(t *testing.T) { testHashToNat(t, P384()) }) + t.Run("P-521", func(t *testing.T) { testHashToNat(t, P521()) }) +} + +func testHashToNat[P Point[P]](t *testing.T, c *Curve[P]) { + for l := 0; l < 600; l++ { + h := bytes.Repeat([]byte{0xff}, l) + hashToNat(c, bigmod.NewNat(), h) + } +} diff --git a/crypto/internal/fips140/ecdsa/hmacdrbg.go b/crypto/internal/fips140/ecdsa/hmacdrbg.go new file mode 100644 index 00000000000..285a614f798 --- /dev/null +++ b/crypto/internal/fips140/ecdsa/hmacdrbg.go @@ -0,0 +1,177 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "bytes" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac" +) + +// hmacDRBG is an SP 800-90A Rev. 1 HMAC_DRBG. +// +// It is only intended to be used to generate ECDSA nonces. Since it will be +// instantiated ex-novo for each signature, its Generate function will only be +// invoked once or twice (only for P-256, with probability 2⁻³²). +// +// Per Table 2, it has a reseed interval of 2^48 requests, and a maximum request +// size of 2^19 bits (2^16 bytes, 64 KiB). +type hmacDRBG struct { + newHMAC func(key []byte) *hmac.HMAC + + hK *hmac.HMAC + V []byte + + reseedCounter uint64 +} + +const ( + reseedInterval = 1 << 48 + maxRequestSize = (1 << 19) / 8 +) + +// plainPersonalizationString is used by HMAC_DRBG as-is. +type plainPersonalizationString []byte + +func (plainPersonalizationString) isPersonalizationString() {} + +// Each entry in blockAlignedPersonalizationString is written to the HMAC at a +// block boundary, as specified in draft-irtf-cfrg-det-sigs-with-noise-04, +// Section 4. +type blockAlignedPersonalizationString [][]byte + +func (blockAlignedPersonalizationString) isPersonalizationString() {} + +type personalizationString interface { + isPersonalizationString() +} + +func newDRBG[H hash.Hash](hash func() H, entropy, nonce []byte, s personalizationString) *hmacDRBG { + // HMAC_DRBG_Instantiate_algorithm, per Section 10.1.2.3. + fips140.RecordApproved() + + d := &hmacDRBG{ + newHMAC: func(key []byte) *hmac.HMAC { + return hmac.New(hash, key) + }, + } + size := hash().Size() + + // K = 0x00 0x00 0x00 ... 0x00 + K := make([]byte, size) + + // V = 0x01 0x01 0x01 ... 0x01 + d.V = bytes.Repeat([]byte{0x01}, size) + + // HMAC_DRBG_Update, per Section 10.1.2.2. + // K = HMAC (K, V || 0x00 || provided_data) + h := hmac.New(hash, K) + h.Write(d.V) + h.Write([]byte{0x00}) + h.Write(entropy) + h.Write(nonce) + switch s := s.(type) { + case plainPersonalizationString: + h.Write(s) + case blockAlignedPersonalizationString: + l := len(d.V) + 1 + len(entropy) + len(nonce) + for _, b := range s { + pad000(h, l) + h.Write(b) + l = len(b) + } + } + K = h.Sum(K[:0]) + // V = HMAC (K, V) + h = hmac.New(hash, K) + h.Write(d.V) + d.V = h.Sum(d.V[:0]) + // K = HMAC (K, V || 0x01 || provided_data). + h.Reset() + h.Write(d.V) + h.Write([]byte{0x01}) + h.Write(entropy) + h.Write(nonce) + switch s := s.(type) { + case plainPersonalizationString: + h.Write(s) + case blockAlignedPersonalizationString: + l := len(d.V) + 1 + len(entropy) + len(nonce) + for _, b := range s { + pad000(h, l) + h.Write(b) + l = len(b) + } + } + K = h.Sum(K[:0]) + // V = HMAC (K, V) + h = hmac.New(hash, K) + h.Write(d.V) + d.V = h.Sum(d.V[:0]) + + d.hK = h + d.reseedCounter = 1 + return d +} + +// TestingOnlyNewDRBG creates an SP 800-90A Rev. 1 HMAC_DRBG with a plain +// personalization string. +// +// This should only be used for ACVP testing. hmacDRBG is not intended to be +// used directly. +func TestingOnlyNewDRBG(hash func() hash.Hash, entropy, nonce []byte, s []byte) *hmacDRBG { + return newDRBG(hash, entropy, nonce, plainPersonalizationString(s)) +} + +func pad000(h *hmac.HMAC, writtenSoFar int) { + blockSize := h.BlockSize() + if rem := writtenSoFar % blockSize; rem != 0 { + h.Write(make([]byte, blockSize-rem)) + } +} + +// Generate produces at most maxRequestSize bytes of random data in out. +func (d *hmacDRBG) Generate(out []byte) { + // HMAC_DRBG_Generate_algorithm, per Section 10.1.2.5. + fips140.RecordApproved() + + if len(out) > maxRequestSize { + panic("ecdsa: internal error: request size exceeds maximum") + } + + if d.reseedCounter > reseedInterval { + panic("ecdsa: reseed interval exceeded") + } + + tlen := 0 + for tlen < len(out) { + // V = HMAC_K(V) + // T = T || V + d.hK.Reset() + d.hK.Write(d.V) + d.V = d.hK.Sum(d.V[:0]) + tlen += copy(out[tlen:], d.V) + } + + // Note that if this function shows up on ECDSA-level profiles, this can be + // optimized in the common case by deferring the rest to the next Generate + // call, which will never come in nearly all cases. + + // HMAC_DRBG_Update, per Section 10.1.2.2, without provided_data. + // K = HMAC (K, V || 0x00) + d.hK.Reset() + d.hK.Write(d.V) + d.hK.Write([]byte{0x00}) + K := d.hK.Sum(nil) + // V = HMAC (K, V) + d.hK = d.newHMAC(K) + d.hK.Write(d.V) + d.V = d.hK.Sum(d.V[:0]) + + d.reseedCounter++ +} diff --git a/crypto/internal/fips140/ed25519/cast.go b/crypto/internal/fips140/ed25519/cast.go new file mode 100644 index 00000000000..fb78d345051 --- /dev/null +++ b/crypto/internal/fips140/ed25519/cast.go @@ -0,0 +1,78 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519 + +import ( + "bytes" + "errors" + "sync" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func fipsPCT(k *PrivateKey) error { + return fips140.PCT("Ed25519 sign and verify PCT", func() error { + return pairwiseTest(k) + }) +} + +// pairwiseTest needs to be a top-level function declaration to let the calls +// inline and their allocations not escape. +func pairwiseTest(k *PrivateKey) error { + msg := []byte("PCT") + sig := Sign(k, msg) + // Note that this runs pub.a.SetBytes. If we wanted to make key generation + // in FIPS mode faster, we could reuse A from GenerateKey. But another thing + // that could make it faster is just _not doing a useless self-test_. + pub, err := NewPublicKey(k.PublicKey()) + if err != nil { + return err + } + return Verify(pub, msg, sig) +} + +func signWithoutSelfTest(priv *PrivateKey, message []byte) []byte { + signature := make([]byte, signatureSize) + return signWithDom(signature, priv, message, domPrefixPure, "") +} + +func verifyWithoutSelfTest(pub *PublicKey, message, sig []byte) error { + return verifyWithDom(pub, message, sig, domPrefixPure, "") +} + +var fipsSelfTest = sync.OnceFunc(func() { + fips140.CAST("Ed25519 sign and verify", func() error { + seed := [32]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + msg := []byte("CAST") + want := []byte{ + 0xbd, 0xe7, 0xa5, 0xf3, 0x40, 0x73, 0xb9, 0x5a, + 0x2e, 0x6d, 0x63, 0x20, 0x0a, 0xd5, 0x92, 0x9b, + 0xa2, 0x3d, 0x00, 0x44, 0xb4, 0xc5, 0xfd, 0x62, + 0x1d, 0x5e, 0x33, 0x2f, 0xe4, 0x61, 0x42, 0x31, + 0x5b, 0x10, 0x53, 0x13, 0x4d, 0xcb, 0xd1, 0x1b, + 0x2a, 0xf6, 0xcd, 0x0e, 0xdb, 0x9a, 0xd3, 0x1e, + 0x35, 0xdb, 0x0b, 0xcf, 0x58, 0x90, 0x4f, 0xd7, + 0x69, 0x38, 0xed, 0x30, 0x51, 0x0f, 0xaa, 0x03, + } + k := &PrivateKey{seed: seed} + precomputePrivateKey(k) + pub, err := NewPublicKey(k.PublicKey()) + if err != nil { + return err + } + sig := signWithoutSelfTest(k, msg) + if !bytes.Equal(sig, want) { + return errors.New("unexpected result") + } + return verifyWithoutSelfTest(pub, msg, sig) + }) +}) diff --git a/crypto/internal/fips140/ed25519/ed25519.go b/crypto/internal/fips140/ed25519/ed25519.go new file mode 100644 index 00000000000..625ec64375a --- /dev/null +++ b/crypto/internal/fips140/ed25519/ed25519.go @@ -0,0 +1,342 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519 + +import ( + "bytes" + "errors" + "strconv" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/edwards25519" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" +) + +// See https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ for the +// components of the keys and the moving parts of the algorithm. + +const ( + seedSize = 32 + publicKeySize = 32 + privateKeySize = seedSize + publicKeySize + signatureSize = 64 + sha512Size = 64 +) + +type PrivateKey struct { + seed [seedSize]byte + pub [publicKeySize]byte + s edwards25519.Scalar + prefix [sha512Size / 2]byte +} + +func (priv *PrivateKey) Bytes() []byte { + k := make([]byte, 0, privateKeySize) + k = append(k, priv.seed[:]...) + k = append(k, priv.pub[:]...) + return k +} + +func (priv *PrivateKey) Seed() []byte { + seed := priv.seed + return seed[:] +} + +func (priv *PrivateKey) PublicKey() []byte { + pub := priv.pub + return pub[:] +} + +type PublicKey struct { + a edwards25519.Point + aBytes [32]byte +} + +func (pub *PublicKey) Bytes() []byte { + a := pub.aBytes + return a[:] +} + +// GenerateKey generates a new Ed25519 private key pair. +func GenerateKey() (*PrivateKey, error) { + priv := &PrivateKey{} + return generateKey(priv) +} + +func generateKey(priv *PrivateKey) (*PrivateKey, error) { + fips140.RecordApproved() + drbg.Read(priv.seed[:]) + precomputePrivateKey(priv) + if err := fipsPCT(priv); err != nil { + // This clearly can't happen, but FIPS 140-3 requires that we check. + panic(err) + } + return priv, nil +} + +func NewPrivateKeyFromSeed(seed []byte) (*PrivateKey, error) { + priv := &PrivateKey{} + return newPrivateKeyFromSeed(priv, seed) +} + +func newPrivateKeyFromSeed(priv *PrivateKey, seed []byte) (*PrivateKey, error) { + fips140.RecordApproved() + if l := len(seed); l != seedSize { + return nil, errors.New("ed25519: bad seed length: " + strconv.Itoa(l)) + } + copy(priv.seed[:], seed) + precomputePrivateKey(priv) + if err := fipsPCT(priv); err != nil { + // This clearly can't happen, but FIPS 140-3 requires that we check. + panic(err) + } + return priv, nil +} + +func precomputePrivateKey(priv *PrivateKey) { + hs := sha512.New() + hs.Write(priv.seed[:]) + h := hs.Sum(make([]byte, 0, sha512Size)) + + s, err := priv.s.SetBytesWithClamping(h[:32]) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + A := (&edwards25519.Point{}).ScalarBaseMult(s) + copy(priv.pub[:], A.Bytes()) + + copy(priv.prefix[:], h[32:]) +} + +func NewPrivateKey(priv []byte) (*PrivateKey, error) { + p := &PrivateKey{} + return newPrivateKey(p, priv) +} + +func newPrivateKey(priv *PrivateKey, privBytes []byte) (*PrivateKey, error) { + fips140.RecordApproved() + if l := len(privBytes); l != privateKeySize { + return nil, errors.New("ed25519: bad private key length: " + strconv.Itoa(l)) + } + + copy(priv.seed[:], privBytes[:32]) + + hs := sha512.New() + hs.Write(priv.seed[:]) + h := hs.Sum(make([]byte, 0, sha512Size)) + + if _, err := priv.s.SetBytesWithClamping(h[:32]); err != nil { + panic("ed25519: internal error: setting scalar failed") + } + // Note that we are not decompressing the public key point here, + // because it takes > 20% of the time of a signature generation. + // Signing doesn't use it as a point anyway. + copy(priv.pub[:], privBytes[32:]) + + copy(priv.prefix[:], h[32:]) + + if err := fipsPCT(priv); err != nil { + // This can happen if the application messed with the private key + // encoding, and the public key doesn't match the seed anymore. + return nil, err + } + + return priv, nil +} + +func NewPublicKey(pub []byte) (*PublicKey, error) { + p := &PublicKey{} + return newPublicKey(p, pub) +} + +func newPublicKey(pub *PublicKey, pubBytes []byte) (*PublicKey, error) { + if l := len(pubBytes); l != publicKeySize { + return nil, errors.New("ed25519: bad public key length: " + strconv.Itoa(l)) + } + // SetBytes checks that the point is on the curve. + if _, err := pub.a.SetBytes(pubBytes); err != nil { + return nil, errors.New("ed25519: bad public key") + } + copy(pub.aBytes[:], pubBytes) + return pub, nil +} + +// Domain separation prefixes used to disambiguate Ed25519/Ed25519ph/Ed25519ctx. +// See RFC 8032, Section 2 and Section 5.1. +const ( + // domPrefixPure is empty for pure Ed25519. + domPrefixPure = "" + // domPrefixPh is dom2(phflag=1) for Ed25519ph. It must be followed by the + // uint8-length prefixed context. + domPrefixPh = "SigEd25519 no Ed25519 collisions\x01" + // domPrefixCtx is dom2(phflag=0) for Ed25519ctx. It must be followed by the + // uint8-length prefixed context. + domPrefixCtx = "SigEd25519 no Ed25519 collisions\x00" +) + +func Sign(priv *PrivateKey, message []byte) []byte { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return sign(signature, priv, message) +} + +func sign(signature []byte, priv *PrivateKey, message []byte) []byte { + fipsSelfTest() + fips140.RecordApproved() + return signWithDom(signature, priv, message, domPrefixPure, "") +} + +func SignPH(priv *PrivateKey, message []byte, context string) ([]byte, error) { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return signPH(signature, priv, message, context) +} + +func signPH(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) { + fipsSelfTest() + fips140.RecordApproved() + if l := len(message); l != sha512Size { + return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) + } + if l := len(context); l > 255 { + return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) + } + return signWithDom(signature, priv, message, domPrefixPh, context), nil +} + +func SignCtx(priv *PrivateKey, message []byte, context string) ([]byte, error) { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return signCtx(signature, priv, message, context) +} + +func signCtx(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) { + fipsSelfTest() + // FIPS 186-5 specifies Ed25519 and Ed25519ph (with context), but not Ed25519ctx. + fips140.RecordNonApproved() + // Note that per RFC 8032, Section 5.1, the context SHOULD NOT be empty. + if l := len(context); l > 255 { + return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) + } + return signWithDom(signature, priv, message, domPrefixCtx, context), nil +} + +func signWithDom(signature []byte, priv *PrivateKey, message []byte, domPrefix, context string) []byte { + mh := sha512.New() + if domPrefix != domPrefixPure { + mh.Write([]byte(domPrefix)) + mh.Write([]byte{byte(len(context))}) + mh.Write([]byte(context)) + } + mh.Write(priv.prefix[:]) + mh.Write(message) + messageDigest := make([]byte, 0, sha512Size) + messageDigest = mh.Sum(messageDigest) + r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + R := (&edwards25519.Point{}).ScalarBaseMult(r) + + kh := sha512.New() + if domPrefix != domPrefixPure { + kh.Write([]byte(domPrefix)) + kh.Write([]byte{byte(len(context))}) + kh.Write([]byte(context)) + } + kh.Write(R.Bytes()) + kh.Write(priv.pub[:]) + kh.Write(message) + hramDigest := make([]byte, 0, sha512Size) + hramDigest = kh.Sum(hramDigest) + k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + S := edwards25519.NewScalar().MultiplyAdd(k, &priv.s, r) + + copy(signature[:32], R.Bytes()) + copy(signature[32:], S.Bytes()) + + return signature +} + +func Verify(pub *PublicKey, message, sig []byte) error { + return verify(pub, message, sig) +} + +func verify(pub *PublicKey, message, sig []byte) error { + fipsSelfTest() + fips140.RecordApproved() + return verifyWithDom(pub, message, sig, domPrefixPure, "") +} + +func VerifyPH(pub *PublicKey, message []byte, sig []byte, context string) error { + fipsSelfTest() + fips140.RecordApproved() + if l := len(message); l != sha512Size { + return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) + } + if l := len(context); l > 255 { + return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) + } + return verifyWithDom(pub, message, sig, domPrefixPh, context) +} + +func VerifyCtx(pub *PublicKey, message []byte, sig []byte, context string) error { + fipsSelfTest() + // FIPS 186-5 specifies Ed25519 and Ed25519ph (with context), but not Ed25519ctx. + fips140.RecordNonApproved() + if l := len(context); l > 255 { + return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) + } + return verifyWithDom(pub, message, sig, domPrefixCtx, context) +} + +func verifyWithDom(pub *PublicKey, message, sig []byte, domPrefix, context string) error { + if l := len(sig); l != signatureSize { + return errors.New("ed25519: bad signature length: " + strconv.Itoa(l)) + } + + if sig[63]&224 != 0 { + return errors.New("ed25519: invalid signature") + } + + kh := sha512.New() + if domPrefix != domPrefixPure { + kh.Write([]byte(domPrefix)) + kh.Write([]byte{byte(len(context))}) + kh.Write([]byte(context)) + } + kh.Write(sig[:32]) + kh.Write(pub.aBytes[:]) + kh.Write(message) + hramDigest := make([]byte, 0, sha512Size) + hramDigest = kh.Sum(hramDigest) + k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) + if err != nil { + return errors.New("ed25519: invalid signature") + } + + // [S]B = R + [k]A --> [k](-A) + [S]B = R + minusA := (&edwards25519.Point{}).Negate(&pub.a) + R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) + + if !bytes.Equal(sig[:32], R.Bytes()) { + return errors.New("ed25519: invalid signature") + } + return nil +} diff --git a/crypto/internal/edwards25519/doc.go b/crypto/internal/fips140/edwards25519/doc.go similarity index 100% rename from crypto/internal/edwards25519/doc.go rename to crypto/internal/fips140/edwards25519/doc.go diff --git a/crypto/internal/edwards25519/edwards25519.go b/crypto/internal/fips140/edwards25519/edwards25519.go similarity index 98% rename from crypto/internal/edwards25519/edwards25519.go rename to crypto/internal/fips140/edwards25519/edwards25519.go index 90d86c17375..3536a72f351 100644 --- a/crypto/internal/edwards25519/edwards25519.go +++ b/crypto/internal/fips140/edwards25519/edwards25519.go @@ -6,7 +6,10 @@ package edwards25519 import ( "errors" - "github.com/runZeroInc/excrypto/crypto/internal/edwards25519/field" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/edwards25519/field" ) // Point types. diff --git a/crypto/internal/edwards25519/edwards25519_test.go b/crypto/internal/fips140/edwards25519/edwards25519_test.go similarity index 94% rename from crypto/internal/edwards25519/edwards25519_test.go rename to crypto/internal/fips140/edwards25519/edwards25519_test.go index f4b76ddb899..687a3147867 100644 --- a/crypto/internal/edwards25519/edwards25519_test.go +++ b/crypto/internal/fips140/edwards25519/edwards25519_test.go @@ -6,10 +6,10 @@ package edwards25519 import ( "encoding/hex" - "github.com/runZeroInc/excrypto/crypto/internal/edwards25519/field" - "github.com/runZeroInc/excrypto/internal/testenv" "reflect" "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/edwards25519/field" ) var B = NewGeneratorPoint() @@ -277,22 +277,6 @@ func TestNonCanonicalPoints(t *testing.T) { } } -var testAllocationsSink byte - -func TestAllocations(t *testing.T) { - testenv.SkipIfOptimizationOff(t) - - if allocs := testing.AllocsPerRun(100, func() { - p := NewIdentityPoint() - p.Add(p, NewGeneratorPoint()) - s := NewScalar() - testAllocationsSink ^= s.Bytes()[0] - testAllocationsSink ^= p.Bytes()[0] - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1v", allocs) - } -} - func decodeHex(s string) []byte { b, err := hex.DecodeString(s) if err != nil { diff --git a/crypto/internal/edwards25519/field/_asm/fe_amd64_asm.go b/crypto/internal/fips140/edwards25519/field/_asm/fe_amd64_asm.go similarity index 92% rename from crypto/internal/edwards25519/field/_asm/fe_amd64_asm.go rename to crypto/internal/fips140/edwards25519/field/_asm/fe_amd64_asm.go index 7f60c198570..ecb713b3c42 100644 --- a/crypto/internal/edwards25519/field/_asm/fe_amd64_asm.go +++ b/crypto/internal/fips140/edwards25519/field/_asm/fe_amd64_asm.go @@ -16,7 +16,7 @@ import ( //go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field func main() { - Package("github.com/runZeroInc/excrypto/crypto/internal/edwards25519/field") + Package("crypto/internal/fips140/edwards25519/field") ConstraintExpr("!purego") feMul() feSquare() @@ -256,6 +256,23 @@ func addMul64(r uint128, i uint64, aX, bX namedComponent) { case 1: Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX)) Load(aX, RAX) + case 2: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + Load(aX, RAX) + SHLQ(U8(1), RAX) + case 19: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + // 19 * v ==> v + (v+v*8)*2 + tmp := Load(aX, GP64()) + LEAQ(Mem{Base: tmp, Index: tmp, Scale: 8}, RAX) + LEAQ(Mem{Base: tmp, Index: RAX, Scale: 2}, RAX) + case 38: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + // 38 * v ==> (v + (v+v*8)*2) * 2 + tmp := Load(aX, GP64()) + LEAQ(Mem{Base: tmp, Index: tmp, Scale: 8}, RAX) + LEAQ(Mem{Base: tmp, Index: RAX, Scale: 2}, RAX) + SHLQ(U8(1), RAX) default: Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) IMUL3Q(Imm(i), Load(aX, GP64()), RAX) diff --git a/crypto/internal/fips140/edwards25519/field/_asm/go.mod b/crypto/internal/fips140/edwards25519/field/_asm/go.mod new file mode 100644 index 00000000000..04cddd3507a --- /dev/null +++ b/crypto/internal/fips140/edwards25519/field/_asm/go.mod @@ -0,0 +1,10 @@ +module crypto/internal/fips140/edwards25519/field/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.14.0 // indirect + golang.org/x/tools v0.16.1 // indirect +) diff --git a/crypto/internal/fips140/edwards25519/field/_asm/go.sum b/crypto/internal/fips140/edwards25519/field/_asm/go.sum new file mode 100644 index 00000000000..483bba88396 --- /dev/null +++ b/crypto/internal/fips140/edwards25519/field/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= diff --git a/crypto/internal/edwards25519/field/fe.go b/crypto/internal/fips140/edwards25519/field/fe.go similarity index 91% rename from crypto/internal/edwards25519/field/fe.go rename to crypto/internal/fips140/edwards25519/field/fe.go index c4a5dbd96dc..fa05327a530 100644 --- a/crypto/internal/edwards25519/field/fe.go +++ b/crypto/internal/fips140/edwards25519/field/fe.go @@ -7,9 +7,12 @@ package field import ( "errors" - "github.com/runZeroInc/excrypto/crypto/subtle" - "github.com/runZeroInc/excrypto/internal/byteorder" "math/bits" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" ) // Element represents an element of the field GF(2^255-19). Note that this @@ -90,11 +93,7 @@ func (v *Element) Add(a, b *Element) *Element { v.l2 = a.l2 + b.l2 v.l3 = a.l3 + b.l3 v.l4 = a.l4 + b.l4 - // Using the generic implementation here is actually faster than the - // assembly. Probably because the body of this function is so simple that - // the compiler can figure out better optimizations by inlining the carry - // propagation. - return v.carryPropagateGeneric() + return v.carryPropagate() } // Subtract sets v = a - b, and returns v. @@ -201,20 +200,20 @@ func (v *Element) SetBytes(x []byte) (*Element, error) { } // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). - v.l0 = byteorder.LeUint64(x[0:8]) + v.l0 = byteorder.LEUint64(x[0:8]) v.l0 &= maskLow51Bits // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). - v.l1 = byteorder.LeUint64(x[6:14]) >> 3 + v.l1 = byteorder.LEUint64(x[6:14]) >> 3 v.l1 &= maskLow51Bits // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). - v.l2 = byteorder.LeUint64(x[12:20]) >> 6 + v.l2 = byteorder.LEUint64(x[12:20]) >> 6 v.l2 &= maskLow51Bits // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). - v.l3 = byteorder.LeUint64(x[19:27]) >> 1 + v.l3 = byteorder.LEUint64(x[19:27]) >> 1 v.l3 &= maskLow51Bits // Bits 204:255 (bytes 24:32, bits 192:256, shift 12, mask 51). // Note: not bytes 25:33, shift 4, to avoid overread. - v.l4 = byteorder.LeUint64(x[24:32]) >> 12 + v.l4 = byteorder.LEUint64(x[24:32]) >> 12 v.l4 &= maskLow51Bits return v, nil @@ -232,18 +231,22 @@ func (v *Element) bytes(out *[32]byte) []byte { t := *v t.reduce() - var buf [8]byte - for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { - bitsOffset := i * 51 - byteorder.LePutUint64(buf[:], l<= len(out) { - break - } - out[off] |= bb - } - } + // Pack five 51-bit limbs into four 64-bit words: + // + // 255 204 153 102 51 0 + // ├──l4──┼──l3──┼──l2──┼──l1──┼──l0──┤ + // ├───u3───┼───u2───┼───u1───┼───u0───┤ + // 256 192 128 64 0 + + u0 := t.l1<<51 | t.l0 + u1 := t.l2<<(102-64) | t.l1>>(64-51) + u2 := t.l3<<(153-128) | t.l2>>(128-102) + u3 := t.l4<<(204-192) | t.l3>>(192-153) + + byteorder.LEPutUint64(out[0*8:], u0) + byteorder.LEPutUint64(out[1*8:], u1) + byteorder.LEPutUint64(out[2*8:], u2) + byteorder.LEPutUint64(out[3*8:], u3) return out[:] } diff --git a/crypto/internal/edwards25519/field/fe_alias_test.go b/crypto/internal/fips140/edwards25519/field/fe_alias_test.go similarity index 100% rename from crypto/internal/edwards25519/field/fe_alias_test.go rename to crypto/internal/fips140/edwards25519/field/fe_alias_test.go diff --git a/crypto/internal/edwards25519/field/fe_amd64.go b/crypto/internal/fips140/edwards25519/field/fe_amd64.go similarity index 100% rename from crypto/internal/edwards25519/field/fe_amd64.go rename to crypto/internal/fips140/edwards25519/field/fe_amd64.go diff --git a/crypto/internal/edwards25519/field/fe_amd64.s b/crypto/internal/fips140/edwards25519/field/fe_amd64.s similarity index 70% rename from crypto/internal/edwards25519/field/fe_amd64.s rename to crypto/internal/fips140/edwards25519/field/fe_amd64.s index 657851c85ed..5e06e242ed8 100644 --- a/crypto/internal/edwards25519/field/fe_amd64.s +++ b/crypto/internal/fips140/edwards25519/field/fe_amd64.s @@ -16,32 +16,36 @@ TEXT ·feMul(SB), NOSPLIT, $0-24 MOVQ DX, SI // r0 += 19×a1×b4 - MOVQ 8(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, DI - ADCQ DX, SI + MOVQ 8(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 32(BX) + ADDQ AX, DI + ADCQ DX, SI // r0 += 19×a2×b3 - MOVQ 16(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, DI - ADCQ DX, SI + MOVQ 16(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 24(BX) + ADDQ AX, DI + ADCQ DX, SI // r0 += 19×a3×b2 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 16(BX) - ADDQ AX, DI - ADCQ DX, SI + MOVQ 24(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 16(BX) + ADDQ AX, DI + ADCQ DX, SI // r0 += 19×a4×b1 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 8(BX) - ADDQ AX, DI - ADCQ DX, SI + MOVQ 32(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 8(BX) + ADDQ AX, DI + ADCQ DX, SI // r1 = a0×b1 MOVQ (CX), AX @@ -56,25 +60,28 @@ TEXT ·feMul(SB), NOSPLIT, $0-24 ADCQ DX, R8 // r1 += 19×a2×b4 - MOVQ 16(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R9 - ADCQ DX, R8 + MOVQ 16(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 32(BX) + ADDQ AX, R9 + ADCQ DX, R8 // r1 += 19×a3×b3 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, R9 - ADCQ DX, R8 + MOVQ 24(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 24(BX) + ADDQ AX, R9 + ADCQ DX, R8 // r1 += 19×a4×b2 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 16(BX) - ADDQ AX, R9 - ADCQ DX, R8 + MOVQ 32(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 16(BX) + ADDQ AX, R9 + ADCQ DX, R8 // r2 = a0×b2 MOVQ (CX), AX @@ -95,18 +102,20 @@ TEXT ·feMul(SB), NOSPLIT, $0-24 ADCQ DX, R10 // r2 += 19×a3×b4 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R11 - ADCQ DX, R10 + MOVQ 24(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 32(BX) + ADDQ AX, R11 + ADCQ DX, R10 // r2 += 19×a4×b3 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, R11 - ADCQ DX, R10 + MOVQ 32(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 24(BX) + ADDQ AX, R11 + ADCQ DX, R10 // r3 = a0×b3 MOVQ (CX), AX @@ -133,11 +142,12 @@ TEXT ·feMul(SB), NOSPLIT, $0-24 ADCQ DX, R12 // r3 += 19×a4×b4 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R13 - ADCQ DX, R12 + MOVQ 32(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 32(BX) + ADDQ AX, R13 + ADCQ DX, R12 // r4 = a0×b4 MOVQ (CX), AX @@ -231,18 +241,22 @@ TEXT ·feSquare(SB), NOSPLIT, $0-16 MOVQ DX, BX // r0 += 38×l1×l4 - MOVQ 8(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, SI - ADCQ DX, BX + MOVQ 8(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + SHLQ $0x01, AX + MULQ 32(CX) + ADDQ AX, SI + ADCQ DX, BX // r0 += 38×l2×l3 - MOVQ 16(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 24(CX) - ADDQ AX, SI - ADCQ DX, BX + MOVQ 16(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + SHLQ $0x01, AX + MULQ 24(CX) + ADDQ AX, SI + ADCQ DX, BX // r1 = 2×l0×l1 MOVQ (CX), AX @@ -252,18 +266,21 @@ TEXT ·feSquare(SB), NOSPLIT, $0-16 MOVQ DX, DI // r1 += 38×l2×l4 - MOVQ 16(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, R8 - ADCQ DX, DI + MOVQ 16(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + SHLQ $0x01, AX + MULQ 32(CX) + ADDQ AX, R8 + ADCQ DX, DI // r1 += 19×l3×l3 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(CX) - ADDQ AX, R8 - ADCQ DX, DI + MOVQ 24(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 24(CX) + ADDQ AX, R8 + ADCQ DX, DI // r2 = 2×l0×l2 MOVQ (CX), AX @@ -279,11 +296,13 @@ TEXT ·feSquare(SB), NOSPLIT, $0-16 ADCQ DX, R9 // r2 += 38×l3×l4 - MOVQ 24(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, R10 - ADCQ DX, R9 + MOVQ 24(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + SHLQ $0x01, AX + MULQ 32(CX) + ADDQ AX, R10 + ADCQ DX, R9 // r3 = 2×l0×l3 MOVQ (CX), AX @@ -293,18 +312,19 @@ TEXT ·feSquare(SB), NOSPLIT, $0-16 MOVQ DX, R11 // r3 += 2×l1×l2 - MOVQ 8(CX), AX - IMUL3Q $0x02, AX, AX - MULQ 16(CX) - ADDQ AX, R12 - ADCQ DX, R11 + MOVQ 8(CX), AX + SHLQ $0x01, AX + MULQ 16(CX) + ADDQ AX, R12 + ADCQ DX, R11 // r3 += 19×l4×l4 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(CX) - ADDQ AX, R12 - ADCQ DX, R11 + MOVQ 32(CX), DX + LEAQ (DX)(DX*8), AX + LEAQ (DX)(AX*2), AX + MULQ 32(CX) + ADDQ AX, R12 + ADCQ DX, R11 // r4 = 2×l0×l4 MOVQ (CX), AX @@ -314,11 +334,11 @@ TEXT ·feSquare(SB), NOSPLIT, $0-16 MOVQ DX, R13 // r4 += 2×l1×l3 - MOVQ 8(CX), AX - IMUL3Q $0x02, AX, AX - MULQ 24(CX) - ADDQ AX, R14 - ADCQ DX, R13 + MOVQ 8(CX), AX + SHLQ $0x01, AX + MULQ 24(CX) + ADDQ AX, R14 + ADCQ DX, R13 // r4 += l2×l2 MOVQ 16(CX), AX diff --git a/crypto/internal/edwards25519/field/fe_amd64_noasm.go b/crypto/internal/fips140/edwards25519/field/fe_amd64_noasm.go similarity index 100% rename from crypto/internal/edwards25519/field/fe_amd64_noasm.go rename to crypto/internal/fips140/edwards25519/field/fe_amd64_noasm.go diff --git a/crypto/internal/edwards25519/field/fe_bench_test.go b/crypto/internal/fips140/edwards25519/field/fe_bench_test.go similarity index 88% rename from crypto/internal/edwards25519/field/fe_bench_test.go rename to crypto/internal/fips140/edwards25519/field/fe_bench_test.go index 84fdf05a8e4..fb80ca88fe2 100644 --- a/crypto/internal/edwards25519/field/fe_bench_test.go +++ b/crypto/internal/fips140/edwards25519/field/fe_bench_test.go @@ -47,3 +47,11 @@ func BenchmarkMult32(b *testing.B) { x.Mult32(x, 0xaa42aa42) } } + +func BenchmarkBytes(b *testing.B) { + x := new(Element).One() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Bytes() + } +} diff --git a/crypto/internal/edwards25519/field/fe_generic.go b/crypto/internal/fips140/edwards25519/field/fe_generic.go similarity index 71% rename from crypto/internal/edwards25519/field/fe_generic.go rename to crypto/internal/fips140/edwards25519/field/fe_generic.go index 86f5fd95534..ef1f15a5dc0 100644 --- a/crypto/internal/edwards25519/field/fe_generic.go +++ b/crypto/internal/fips140/edwards25519/field/fe_generic.go @@ -12,20 +12,42 @@ type uint128 struct { lo, hi uint64 } -// mul64 returns a * b. -func mul64(a, b uint64) uint128 { +// mul returns a * b. +func mul(a, b uint64) uint128 { hi, lo := bits.Mul64(a, b) return uint128{lo, hi} } -// addMul64 returns v + a * b. -func addMul64(v uint128, a, b uint64) uint128 { +// addMul returns v + a * b. +func addMul(v uint128, a, b uint64) uint128 { hi, lo := bits.Mul64(a, b) lo, c := bits.Add64(lo, v.lo, 0) hi, _ = bits.Add64(hi, v.hi, c) return uint128{lo, hi} } +// mul19 returns v * 19. +func mul19(v uint64) uint64 { + // Using this approach seems to yield better optimizations than *19. + return v + (v+v<<3)<<1 +} + +// addMul19 returns v + 19 * a * b, where a and b are at most 52 bits. +func addMul19(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(mul19(a), b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// addMul38 returns v + 38 * a * b, where a and b are at most 52 bits. +func addMul38(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(mul19(a), b*2) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + // shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. func shiftRightBy51(a uint128) uint64 { return (a.hi << (64 - 51)) | (a.lo >> 51) @@ -76,45 +98,40 @@ func feMulGeneric(v, a, b *Element) { // // Finally we add up the columns into wide, overlapping limbs. - a1_19 := a1 * 19 - a2_19 := a2 * 19 - a3_19 := a3 * 19 - a4_19 := a4 * 19 - // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) - r0 := mul64(a0, b0) - r0 = addMul64(r0, a1_19, b4) - r0 = addMul64(r0, a2_19, b3) - r0 = addMul64(r0, a3_19, b2) - r0 = addMul64(r0, a4_19, b1) + r0 := mul(a0, b0) + r0 = addMul19(r0, a1, b4) + r0 = addMul19(r0, a2, b3) + r0 = addMul19(r0, a3, b2) + r0 = addMul19(r0, a4, b1) // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) - r1 := mul64(a0, b1) - r1 = addMul64(r1, a1, b0) - r1 = addMul64(r1, a2_19, b4) - r1 = addMul64(r1, a3_19, b3) - r1 = addMul64(r1, a4_19, b2) + r1 := mul(a0, b1) + r1 = addMul(r1, a1, b0) + r1 = addMul19(r1, a2, b4) + r1 = addMul19(r1, a3, b3) + r1 = addMul19(r1, a4, b2) // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) - r2 := mul64(a0, b2) - r2 = addMul64(r2, a1, b1) - r2 = addMul64(r2, a2, b0) - r2 = addMul64(r2, a3_19, b4) - r2 = addMul64(r2, a4_19, b3) + r2 := mul(a0, b2) + r2 = addMul(r2, a1, b1) + r2 = addMul(r2, a2, b0) + r2 = addMul19(r2, a3, b4) + r2 = addMul19(r2, a4, b3) // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 - r3 := mul64(a0, b3) - r3 = addMul64(r3, a1, b2) - r3 = addMul64(r3, a2, b1) - r3 = addMul64(r3, a3, b0) - r3 = addMul64(r3, a4_19, b4) + r3 := mul(a0, b3) + r3 = addMul(r3, a1, b2) + r3 = addMul(r3, a2, b1) + r3 = addMul(r3, a3, b0) + r3 = addMul19(r3, a4, b4) // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 - r4 := mul64(a0, b4) - r4 = addMul64(r4, a1, b3) - r4 = addMul64(r4, a2, b2) - r4 = addMul64(r4, a3, b1) - r4 = addMul64(r4, a4, b0) + r4 := mul(a0, b4) + r4 = addMul(r4, a1, b3) + r4 = addMul(r4, a2, b2) + r4 = addMul(r4, a3, b1) + r4 = addMul(r4, a4, b0) // After the multiplication, we need to reduce (carry) the five coefficients // to obtain a result with limbs that are at most slightly larger than 2⁵¹, @@ -149,7 +166,7 @@ func feMulGeneric(v, a, b *Element) { c3 := shiftRightBy51(r3) c4 := shiftRightBy51(r4) - rr0 := r0.lo&maskLow51Bits + c4*19 + rr0 := r0.lo&maskLow51Bits + mul19(c4) rr1 := r1.lo&maskLow51Bits + c0 rr2 := r2.lo&maskLow51Bits + c1 rr3 := r3.lo&maskLow51Bits + c2 @@ -158,8 +175,12 @@ func feMulGeneric(v, a, b *Element) { // Now all coefficients fit into 64-bit registers but are still too large to // be passed around as an Element. We therefore do one last carry chain, // where the carries will be small enough to fit in the wiggle room above 2⁵¹. - *v = Element{rr0, rr1, rr2, rr3, rr4} - v.carryPropagate() + + v.l0 = rr0&maskLow51Bits + mul19(rr4>>51) + v.l1 = rr1&maskLow51Bits + rr0>>51 + v.l2 = rr2&maskLow51Bits + rr1>>51 + v.l3 = rr3&maskLow51Bits + rr2>>51 + v.l4 = rr4&maskLow51Bits + rr3>>51 } func feSquareGeneric(v, a *Element) { @@ -190,44 +211,31 @@ func feSquareGeneric(v, a *Element) { // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = // -------------------------------------- // r4 r3 r2 r1 r0 - // - // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with - // only three Mul64 and four Add64, instead of five and eight. - - l0_2 := l0 * 2 - l1_2 := l1 * 2 - - l1_38 := l1 * 38 - l2_38 := l2 * 38 - l3_38 := l3 * 38 - - l3_19 := l3 * 19 - l4_19 := l4 * 19 // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) - r0 := mul64(l0, l0) - r0 = addMul64(r0, l1_38, l4) - r0 = addMul64(r0, l2_38, l3) + r0 := mul(l0, l0) + r0 = addMul38(r0, l1, l4) + r0 = addMul38(r0, l2, l3) // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 - r1 := mul64(l0_2, l1) - r1 = addMul64(r1, l2_38, l4) - r1 = addMul64(r1, l3_19, l3) + r1 := mul(l0*2, l1) + r1 = addMul38(r1, l2, l4) + r1 = addMul19(r1, l3, l3) // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 - r2 := mul64(l0_2, l2) - r2 = addMul64(r2, l1, l1) - r2 = addMul64(r2, l3_38, l4) + r2 := mul(l0*2, l2) + r2 = addMul(r2, l1, l1) + r2 = addMul38(r2, l3, l4) // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 - r3 := mul64(l0_2, l3) - r3 = addMul64(r3, l1_2, l2) - r3 = addMul64(r3, l4_19, l4) + r3 := mul(l0*2, l3) + r3 = addMul(r3, l1*2, l2) + r3 = addMul19(r3, l4, l4) // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 - r4 := mul64(l0_2, l4) - r4 = addMul64(r4, l1_2, l3) - r4 = addMul64(r4, l2, l2) + r4 := mul(l0*2, l4) + r4 = addMul(r4, l1*2, l3) + r4 = addMul(r4, l2, l2) c0 := shiftRightBy51(r0) c1 := shiftRightBy51(r1) @@ -235,32 +243,30 @@ func feSquareGeneric(v, a *Element) { c3 := shiftRightBy51(r3) c4 := shiftRightBy51(r4) - rr0 := r0.lo&maskLow51Bits + c4*19 + rr0 := r0.lo&maskLow51Bits + mul19(c4) rr1 := r1.lo&maskLow51Bits + c0 rr2 := r2.lo&maskLow51Bits + c1 rr3 := r3.lo&maskLow51Bits + c2 rr4 := r4.lo&maskLow51Bits + c3 - *v = Element{rr0, rr1, rr2, rr3, rr4} - v.carryPropagate() + v.l0 = rr0&maskLow51Bits + mul19(rr4>>51) + v.l1 = rr1&maskLow51Bits + rr0>>51 + v.l2 = rr2&maskLow51Bits + rr1>>51 + v.l3 = rr3&maskLow51Bits + rr2>>51 + v.l4 = rr4&maskLow51Bits + rr3>>51 } -// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction +// carryPropagate brings the limbs below 52 bits by applying the reduction // identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. -func (v *Element) carryPropagateGeneric() *Element { - c0 := v.l0 >> 51 - c1 := v.l1 >> 51 - c2 := v.l2 >> 51 - c3 := v.l3 >> 51 - c4 := v.l4 >> 51 - - // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and +func (v *Element) carryPropagate() *Element { + // (l4>>51) is at most 64 - 51 = 13 bits, so (l4>>51)*19 is at most 18 bits, and // the final l0 will be at most 52 bits. Similarly for the rest. - v.l0 = v.l0&maskLow51Bits + c4*19 - v.l1 = v.l1&maskLow51Bits + c0 - v.l2 = v.l2&maskLow51Bits + c1 - v.l3 = v.l3&maskLow51Bits + c2 - v.l4 = v.l4&maskLow51Bits + c3 + l0 := v.l0 + v.l0 = v.l0&maskLow51Bits + mul19(v.l4>>51) + v.l4 = v.l4&maskLow51Bits + v.l3>>51 + v.l3 = v.l3&maskLow51Bits + v.l2>>51 + v.l2 = v.l2&maskLow51Bits + v.l1>>51 + v.l1 = v.l1&maskLow51Bits + l0>>51 return v } diff --git a/crypto/internal/edwards25519/field/fe_test.go b/crypto/internal/fips140/edwards25519/field/fe_test.go similarity index 83% rename from crypto/internal/edwards25519/field/fe_test.go rename to crypto/internal/fips140/edwards25519/field/fe_test.go index cf07662048c..b2688789121 100644 --- a/crypto/internal/edwards25519/field/fe_test.go +++ b/crypto/internal/fips140/edwards25519/field/fe_test.go @@ -6,6 +6,7 @@ package field import ( "bytes" + "crypto/rand" "encoding/hex" "io" "math/big" @@ -14,8 +15,6 @@ import ( "reflect" "testing" "testing/quick" - - "crypto/rand" ) func (v Element) String() string { @@ -129,25 +128,25 @@ func TestMultiplyDistributesOverAdd(t *testing.T) { func TestMul64to128(t *testing.T) { a := uint64(5) b := uint64(5) - r := mul64(a, b) + r := mul(a, b) if r.lo != 0x19 || r.hi != 0 { t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) } a = uint64(18014398509481983) // 2^54 - 1 b = uint64(18014398509481983) // 2^54 - 1 - r = mul64(a, b) + r = mul(a, b) if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff { t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) } a = uint64(1125899906842661) b = uint64(2097155) - r = mul64(a, b) - r = addMul64(r, a, b) - r = addMul64(r, a, b) - r = addMul64(r, a, b) - r = addMul64(r, a, b) + r = mul(a, b) + r = addMul(r, a, b) + r = addMul(r, a, b) + r = addMul(r, a, b) + r = addMul(r, a, b) if r.lo != 16888498990613035 || r.hi != 640 { t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi) } @@ -434,55 +433,55 @@ func TestMult32(t *testing.T) { func TestSqrtRatio(t *testing.T) { // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. type test struct { - u, v string + u, v []byte wasSquare int - r string + r []byte } var tests = []test{ // If u is 0, the function is defined to return (0, TRUE), even if v // is zero. Note that where used in this package, the denominator v // is never zero. { - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - 1, "0000000000000000000000000000000000000000000000000000000000000000", + decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), + 1, decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), }, // 0/1 == 0² { - "0000000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - 1, "0000000000000000000000000000000000000000000000000000000000000000", + decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0100000000000000000000000000000000000000000000000000000000000000"), + 1, decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), }, // If u is non-zero and v is zero, defined to return (0, FALSE). { - "0100000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - 0, "0000000000000000000000000000000000000000000000000000000000000000", + decodeHex("0100000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), + 0, decodeHex("0000000000000000000000000000000000000000000000000000000000000000"), }, // 2/1 is not square in this field. { - "0200000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - 0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54", + decodeHex("0200000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0100000000000000000000000000000000000000000000000000000000000000"), + 0, decodeHex("3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54"), }, // 4/1 == 2² { - "0400000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - 1, "0200000000000000000000000000000000000000000000000000000000000000", + decodeHex("0400000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0100000000000000000000000000000000000000000000000000000000000000"), + 1, decodeHex("0200000000000000000000000000000000000000000000000000000000000000"), }, // 1/4 == (2⁻¹)² == (2^(p-2))² per Euler's theorem { - "0100000000000000000000000000000000000000000000000000000000000000", - "0400000000000000000000000000000000000000000000000000000000000000", - 1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f", + decodeHex("0100000000000000000000000000000000000000000000000000000000000000"), + decodeHex("0400000000000000000000000000000000000000000000000000000000000000"), + 1, decodeHex("f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f"), }, } for i, tt := range tests { - u, _ := new(Element).SetBytes(decodeHex(tt.u)) - v, _ := new(Element).SetBytes(decodeHex(tt.v)) - want, _ := new(Element).SetBytes(decodeHex(tt.r)) + u, _ := new(Element).SetBytes(tt.u) + v, _ := new(Element).SetBytes(tt.v) + want, _ := new(Element).SetBytes(tt.r) got, wasSquare := new(Element).SqrtRatio(u, v) if got.Equal(want) == 0 || wasSquare != tt.wasSquare { t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare) @@ -490,30 +489,6 @@ func TestSqrtRatio(t *testing.T) { } } -func TestCarryPropagate(t *testing.T) { - asmLikeGeneric := func(a [5]uint64) bool { - t1 := &Element{a[0], a[1], a[2], a[3], a[4]} - t2 := &Element{a[0], a[1], a[2], a[3], a[4]} - - t1.carryPropagate() - t2.carryPropagateGeneric() - - if *t1 != *t2 { - t.Logf("got: %#v,\nexpected: %#v", t1, t2) - } - - return *t1 == *t2 && isInBounds(t2) - } - - if err := quick.Check(asmLikeGeneric, quickCheckConfig(1024)); err != nil { - t.Error(err) - } - - if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) { - t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}") - } -} - func TestFeSquare(t *testing.T) { asmLikeGeneric := func(a Element) bool { t1 := a diff --git a/crypto/internal/edwards25519/scalar.go b/crypto/internal/fips140/edwards25519/scalar.go similarity index 93% rename from crypto/internal/edwards25519/scalar.go rename to crypto/internal/fips140/edwards25519/scalar.go index 17f4d58506c..2b69aee4988 100644 --- a/crypto/internal/edwards25519/scalar.go +++ b/crypto/internal/fips140/edwards25519/scalar.go @@ -6,7 +6,9 @@ package edwards25519 import ( "errors" - "github.com/runZeroInc/excrypto/internal/byteorder" + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" ) // A Scalar is an integer modulo @@ -179,15 +181,23 @@ func isReduced(s []byte) bool { return false } - for i := len(s) - 1; i >= 0; i-- { - switch { - case s[i] > scalarMinusOneBytes[i]: - return false - case s[i] < scalarMinusOneBytes[i]: - return true - } - } - return true + s0 := byteorder.LEUint64(s[:8]) + s1 := byteorder.LEUint64(s[8:16]) + s2 := byteorder.LEUint64(s[16:24]) + s3 := byteorder.LEUint64(s[24:]) + + l0 := byteorder.LEUint64(scalarMinusOneBytes[:8]) + l1 := byteorder.LEUint64(scalarMinusOneBytes[8:16]) + l2 := byteorder.LEUint64(scalarMinusOneBytes[16:24]) + l3 := byteorder.LEUint64(scalarMinusOneBytes[24:]) + + // Do a constant time subtraction chain scalarMinusOneBytes - s. If there is + // a borrow at the end, then s > scalarMinusOneBytes. + _, b := bits.Sub64(l0, s0, 0) + _, b = bits.Sub64(l1, s1, b) + _, b = bits.Sub64(l2, s2, b) + _, b = bits.Sub64(l3, s3, b) + return b == 0 } // SetBytesWithClamping applies the buffer pruning described in RFC 8032, @@ -271,7 +281,7 @@ func (s *Scalar) nonAdjacentForm(w uint) [256]int8 { var digits [5]uint64 for i := 0; i < 4; i++ { - digits[i] = byteorder.LeUint64(b[i*8:]) + digits[i] = byteorder.LEUint64(b[i*8:]) } width := uint64(1 << w) diff --git a/crypto/internal/edwards25519/scalar_alias_test.go b/crypto/internal/fips140/edwards25519/scalar_alias_test.go similarity index 100% rename from crypto/internal/edwards25519/scalar_alias_test.go rename to crypto/internal/fips140/edwards25519/scalar_alias_test.go diff --git a/crypto/internal/edwards25519/scalar_fiat.go b/crypto/internal/fips140/edwards25519/scalar_fiat.go similarity index 100% rename from crypto/internal/edwards25519/scalar_fiat.go rename to crypto/internal/fips140/edwards25519/scalar_fiat.go diff --git a/crypto/internal/edwards25519/scalar_test.go b/crypto/internal/fips140/edwards25519/scalar_test.go similarity index 92% rename from crypto/internal/edwards25519/scalar_test.go rename to crypto/internal/fips140/edwards25519/scalar_test.go index 05551ef7711..76e920a2feb 100644 --- a/crypto/internal/edwards25519/scalar_test.go +++ b/crypto/internal/fips140/edwards25519/scalar_test.go @@ -26,7 +26,7 @@ func quickCheckConfig(slowScale int) *quick.Config { var scOneBytes = [32]byte{1} var scOne, _ = new(Scalar).SetCanonicalBytes(scOneBytes[:]) -var scMinusOne, _ = new(Scalar).SetCanonicalBytes(scalarMinusOneBytes[:]) +var scMinusOne = new(Scalar).Subtract(new(Scalar), scOne) // Generate returns a valid (reduced modulo l) Scalar with a distribution // weighted towards high, low, and edge values. @@ -38,7 +38,7 @@ func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value { case diceRoll == 1: s = scOneBytes case diceRoll == 2: - s = scalarMinusOneBytes + s = [32]byte(scMinusOne.Bytes()) case diceRoll < 5: // Generate a low scalar in [0, 2^125). rand.Read(s[:16]) @@ -96,16 +96,29 @@ func TestScalarSetCanonicalBytes(t *testing.T) { t.Errorf("failed scalar->bytes->scalar round-trip: %v", err) } - b := scalarMinusOneBytes - b[31] += 1 - s := scOne - if out, err := s.SetCanonicalBytes(b[:]); err == nil { - t.Errorf("SetCanonicalBytes worked on a non-canonical value") - } else if s != scOne { - t.Errorf("SetCanonicalBytes modified its receiver") - } else if out != nil { - t.Errorf("SetCanonicalBytes did not return nil with an error") + expectReject := func(b []byte) { + t.Helper() + s := scOne + if out, err := s.SetCanonicalBytes(b[:]); err == nil { + t.Errorf("SetCanonicalBytes worked on a non-canonical value") + } else if s != scOne { + t.Errorf("SetCanonicalBytes modified its receiver") + } else if out != nil { + t.Errorf("SetCanonicalBytes did not return nil with an error") + } } + + b := scMinusOne.Bytes() + b[0] += 1 + expectReject(b) + + b = scMinusOne.Bytes() + b[31] += 1 + expectReject(b) + + b = scMinusOne.Bytes() + b[31] |= 0b1000_0000 + expectReject(b) } func TestScalarSetUniformBytes(t *testing.T) { diff --git a/crypto/internal/edwards25519/scalarmult.go b/crypto/internal/fips140/edwards25519/scalarmult.go similarity index 100% rename from crypto/internal/edwards25519/scalarmult.go rename to crypto/internal/fips140/edwards25519/scalarmult.go diff --git a/crypto/internal/edwards25519/scalarmult_test.go b/crypto/internal/fips140/edwards25519/scalarmult_test.go similarity index 100% rename from crypto/internal/edwards25519/scalarmult_test.go rename to crypto/internal/fips140/edwards25519/scalarmult_test.go diff --git a/crypto/internal/edwards25519/tables.go b/crypto/internal/fips140/edwards25519/tables.go similarity index 98% rename from crypto/internal/edwards25519/tables.go rename to crypto/internal/fips140/edwards25519/tables.go index 8035cdb9013..37ab515dca2 100644 --- a/crypto/internal/edwards25519/tables.go +++ b/crypto/internal/fips140/edwards25519/tables.go @@ -5,7 +5,7 @@ package edwards25519 import ( - "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" ) // A dynamic lookup table for variable-base, constant-time scalar muls. diff --git a/crypto/internal/edwards25519/tables_test.go b/crypto/internal/fips140/edwards25519/tables_test.go similarity index 100% rename from crypto/internal/edwards25519/tables_test.go rename to crypto/internal/fips140/edwards25519/tables_test.go diff --git a/crypto/internal/fips140/fips140.go b/crypto/internal/fips140/fips140.go new file mode 100644 index 00000000000..37ec54b1f71 --- /dev/null +++ b/crypto/internal/fips140/fips140.go @@ -0,0 +1,80 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140 + +import ( + "errors" + "runtime" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" +) + +var Enabled bool + +var debug bool + +func init() { + v := godebug.Value("#fips140") + switch v { + case "on", "only": + Enabled = true + case "debug": + Enabled = true + debug = true + case "off", "": + default: + panic("fips140: unknown GODEBUG setting fips140=" + v) + } +} + +// Supported returns an error if FIPS 140-3 mode can't be enabled. +func Supported() error { + // Keep this in sync with fipsSupported in cmd/dist/test.go. + + // ASAN disapproves of reading swaths of global memory in fips140/check. + // One option would be to expose runtime.asanunpoison through + // crypto/internal/fips140deps and then call it to unpoison the range + // before reading it, but it is unclear whether that would then cause + // false negatives. For now, FIPS+ASAN doesn't need to work. + if asanEnabled { + return errors.New("FIPS 140-3 mode is incompatible with ASAN") + } + + // See EnableFIPS in cmd/internal/obj/fips.go for commentary. + switch { + case runtime.GOARCH == "wasm", + runtime.GOOS == "windows" && runtime.GOARCH == "386", + runtime.GOOS == "windows" && runtime.GOARCH == "arm", + runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880 + runtime.GOOS == "aix": + return errors.New("FIPS 140-3 mode is not supported on " + runtime.GOOS + "-" + runtime.GOARCH) + } + + if boringEnabled { + return errors.New("FIPS 140-3 mode is incompatible with GOEXPERIMENT=boringcrypto") + } + + return nil +} + +func Name() string { + return "Go Cryptographic Module" +} + +// Version returns the formal version (such as "v1.0") if building against a +// frozen module with GOFIPS140. Otherwise, it returns "latest". +func Version() string { + // This return value is replaced by mkzip.go, it must not be changed or + // moved to a different file. + return "latest" //mkzip:version +} + +// Hash is a legacy compatibility alias for hash.Hash. +// +// It's only here because [crypto/internal/fips140/ecdsa.TestingOnlyNewDRBG] +// takes a "func() fips140.Hash" in v1.0.0, instead of being generic. +type Hash = hash.Hash diff --git a/crypto/internal/fips140/hkdf/cast.go b/crypto/internal/fips140/hkdf/cast.go new file mode 100644 index 00000000000..0af93d4f07f --- /dev/null +++ b/crypto/internal/fips140/hkdf/cast.go @@ -0,0 +1,34 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" +) + +func init() { + fips140.CAST("HKDF-SHA2-256", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0xb6, 0x53, 0x00, 0x5b, 0x51, 0x6d, 0x2b, 0xc9, + 0x4a, 0xe4, 0xf9, 0x51, 0x73, 0x1f, 0x71, 0x21, + 0xa6, 0xc1, 0xde, 0x42, 0x4f, 0x2c, 0x99, 0x60, + 0x64, 0xdb, 0x66, 0x3e, 0xec, 0xa6, 0x37, 0xff, + } + got := Key(sha256.New, input, input, string(input), len(want)) + if !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/hkdf/hkdf.go b/crypto/internal/fips140/hkdf/hkdf.go new file mode 100644 index 00000000000..e235ca411c5 --- /dev/null +++ b/crypto/internal/fips140/hkdf/hkdf.go @@ -0,0 +1,58 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf + +import ( + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac" +) + +func Extract[H hash.Hash](h func() H, secret, salt []byte) []byte { + if len(secret) < 112/8 { + fips140.RecordNonApproved() + } + if salt == nil { + salt = make([]byte, h().Size()) + } + extractor := hmac.New(h, salt) + hmac.MarkAsUsedInKDF(extractor) + extractor.Write(secret) + + return extractor.Sum(nil) +} + +func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) []byte { + out := make([]byte, 0, keyLen) + expander := hmac.New(h, pseudorandomKey) + hmac.MarkAsUsedInKDF(expander) + var counter uint8 + var buf []byte + + for len(out) < keyLen { + counter++ + if counter == 0 { + panic("hkdf: counter overflow") + } + if counter > 1 { + expander.Reset() + } + expander.Write(buf) + expander.Write([]byte(info)) + expander.Write([]byte{counter}) + buf = expander.Sum(buf[:0]) + remain := keyLen - len(out) + remain = min(remain, len(buf)) + out = append(out, buf[:remain]...) + } + + return out +} + +func Key[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) []byte { + prk := Extract(h, secret, salt) + return Expand(h, prk, info, keyLen) +} diff --git a/crypto/internal/fips140/hmac/cast.go b/crypto/internal/fips140/hmac/cast.go new file mode 100644 index 00000000000..bef36e79df1 --- /dev/null +++ b/crypto/internal/fips140/hmac/cast.go @@ -0,0 +1,35 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hmac + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" +) + +func init() { + fips140.CAST("HMAC-SHA2-256", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0xf0, 0x8d, 0x82, 0x8d, 0x4c, 0x9e, 0xad, 0x3d, + 0xdc, 0x12, 0x9c, 0x4e, 0x70, 0xc4, 0x19, 0x2a, + 0x4f, 0x12, 0x73, 0x23, 0x73, 0x77, 0x66, 0x05, + 0x10, 0xee, 0x57, 0x6b, 0x3a, 0xc7, 0x14, 0x41, + } + h := New(sha256.New, input) + h.Write(input) + h.Write(input) + if got := h.Sum(nil); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/hmac/hmac.go b/crypto/internal/fips140/hmac/hmac.go new file mode 100644 index 00000000000..95af680adcd --- /dev/null +++ b/crypto/internal/fips140/hmac/hmac.go @@ -0,0 +1,210 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package hmac implements HMAC according to [FIPS 198-1]. +// +// [FIPS 198-1]: https://doi.org/10.6028/NIST.FIPS.198-1 +package hmac + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" + "github.com/runZeroInc/excrypto/hash" +) + +// key is zero padded to the block size of the hash function +// ipad = 0x36 byte repeated for key length +// opad = 0x5c byte repeated for key length +// hmac = H([key ^ opad] H([key ^ ipad] text)) + +// marshalable is the combination of encoding.BinaryMarshaler and +// encoding.BinaryUnmarshaler. Their method definitions are repeated here to +// avoid a dependency on the encoding package. +type marshalable interface { + MarshalBinary() ([]byte, error) + UnmarshalBinary([]byte) error +} + +type HMAC struct { + // opad and ipad may share underlying storage with HMAC clones. + opad, ipad []byte + outer, inner hash.Hash + + // If marshaled is true, then opad and ipad do not contain a padded + // copy of the key, but rather the marshaled state of outer/inner after + // opad/ipad has been fed into it. + marshaled bool + + // forHKDF and keyLen are stored to inform the service indicator decision. + forHKDF bool + keyLen int +} + +func (h *HMAC) Sum(in []byte) []byte { + // Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for + // legacy use (i.e. verification only) and we don't support that. However, + // HKDF uses the HMAC key for the salt, which is allowed to be shorter. + if h.keyLen < 112/8 && !h.forHKDF { + fips140.RecordNonApproved() + } + switch h.inner.(type) { + case *sha256.Digest, *sha512.Digest, *sha3.Digest: + default: + fips140.RecordNonApproved() + } + + origLen := len(in) + in = h.inner.Sum(in) + + if h.marshaled { + if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil { + panic(err) + } + } else { + h.outer.Reset() + h.outer.Write(h.opad) + } + h.outer.Write(in[origLen:]) + return h.outer.Sum(in[:origLen]) +} + +func (h *HMAC) Write(p []byte) (n int, err error) { + return h.inner.Write(p) +} + +func (h *HMAC) Size() int { return h.outer.Size() } +func (h *HMAC) BlockSize() int { return h.inner.BlockSize() } + +func (h *HMAC) Reset() { + if h.marshaled { + if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil { + panic(err) + } + return + } + + h.inner.Reset() + h.inner.Write(h.ipad) + + // If the underlying hash is marshalable, we can save some time by saving a + // copy of the hash state now, and restoring it on future calls to Reset and + // Sum instead of writing ipad/opad every time. + // + // We do this on Reset to avoid slowing down the common single-use case. + // + // This is allowed by FIPS 198-1, Section 6: "Conceptually, the intermediate + // results of the compression function on the B-byte blocks (K0 ⊕ ipad) and + // (K0 ⊕ opad) can be precomputed once, at the time of generation of the key + // K, or before its first use. These intermediate results can be stored and + // then used to initialize H each time that a message needs to be + // authenticated using the same key. [...] These stored intermediate values + // shall be treated and protected in the same manner as secret keys." + marshalableInner, innerOK := h.inner.(marshalable) + if !innerOK { + return + } + marshalableOuter, outerOK := h.outer.(marshalable) + if !outerOK { + return + } + + imarshal, err := marshalableInner.MarshalBinary() + if err != nil { + return + } + + h.outer.Reset() + h.outer.Write(h.opad) + omarshal, err := marshalableOuter.MarshalBinary() + if err != nil { + return + } + + // Marshaling succeeded; save the marshaled state for later + h.ipad = imarshal + h.opad = omarshal + h.marshaled = true +} + +type errCloneUnsupported struct{} + +func (e errCloneUnsupported) Error() string { + return "crypto/hmac: hash does not support hash.Cloner" +} + +func (e errCloneUnsupported) Unwrap() error { + return errors.ErrUnsupported +} + +// Clone implements [hash.Cloner] if the underlying hash does. +// Otherwise, it returns an error wrapping [errors.ErrUnsupported]. +func (h *HMAC) Clone() (hash.Cloner, error) { + r := *h + ic, ok := h.inner.(hash.Cloner) + if !ok { + return nil, errCloneUnsupported{} + } + oc, ok := h.outer.(hash.Cloner) + if !ok { + return nil, errCloneUnsupported{} + } + var err error + r.inner, err = ic.Clone() + if err != nil { + return nil, errCloneUnsupported{} + } + r.outer, err = oc.Clone() + if err != nil { + return nil, errCloneUnsupported{} + } + return &r, nil +} + +// New returns a new HMAC hash using the given [hash.Hash] type and key. +func New[H hash.Hash](h func() H, key []byte) *HMAC { + hm := &HMAC{keyLen: len(key)} + hm.outer = h() + hm.inner = h() + unique := true + func() { + defer func() { + // The comparison might panic if the underlying types are not comparable. + _ = recover() + }() + if hm.outer == hm.inner { + unique = false + } + }() + if !unique { + panic("crypto/hmac: hash generation function does not produce unique values") + } + blocksize := hm.inner.BlockSize() + hm.ipad = make([]byte, blocksize) + hm.opad = make([]byte, blocksize) + if len(key) > blocksize { + // If key is too big, hash it. + hm.outer.Write(key) + key = hm.outer.Sum(nil) + } + copy(hm.ipad, key) + copy(hm.opad, key) + for i := range hm.ipad { + hm.ipad[i] ^= 0x36 + } + for i := range hm.opad { + hm.opad[i] ^= 0x5c + } + hm.inner.Write(hm.ipad) + + return hm +} + +// MarkAsUsedInKDF records that this HMAC instance is used as part of a KDF. +func MarkAsUsedInKDF(h *HMAC) { + h.forHKDF = true +} diff --git a/crypto/internal/fips140/indicator.go b/crypto/internal/fips140/indicator.go new file mode 100644 index 00000000000..dd4d3999186 --- /dev/null +++ b/crypto/internal/fips140/indicator.go @@ -0,0 +1,66 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140 + +import _ "unsafe" // for go:linkname + +// The service indicator lets users of the module query whether invoked services +// are approved. Three states are stored in a per-goroutine value by the +// runtime. The indicator starts at indicatorUnset after a reset. Invoking an +// approved service transitions to indicatorTrue. Invoking a non-approved +// service transitions to indicatorFalse, and it can't leave that state until a +// reset. The idea is that functions can "delegate" checks to inner functions, +// and if there's anything non-approved in the stack, the final result is +// negative. Finally, we expose indicatorUnset as negative to the user, so that +// we don't need to explicitly annotate fully non-approved services. + +func getIndicator() uint8 { + return indicatorVal +} + +func setIndicator(v uint8) { + indicatorVal = v +} + +const ( + indicatorUnset uint8 = iota + indicatorFalse + indicatorTrue +) + +var indicatorVal uint8 + +// ResetServiceIndicator clears the service indicator for the running goroutine. +func ResetServiceIndicator() { + setIndicator(indicatorUnset) +} + +// ServiceIndicator returns true if and only if all services invoked by this +// goroutine since the last ResetServiceIndicator call are approved. +// +// If ResetServiceIndicator was not called before by this goroutine, its return +// value is undefined. +func ServiceIndicator() bool { + return getIndicator() == indicatorTrue +} + +// RecordApproved is an internal function that records the use of an approved +// service. It does not override RecordNonApproved calls in the same span. +// +// It should be called by exposed functions that perform a whole cryptographic +// alrgorithm (e.g. by Sum, not by New, unless a cryptographic Instantiate +// algorithm is performed) and should be called after any checks that may cause +// the function to error out or panic. +func RecordApproved() { + if getIndicator() == indicatorUnset { + setIndicator(indicatorTrue) + } +} + +// RecordNonApproved is an internal function that records the use of a +// non-approved service. It overrides any RecordApproved calls in the same span. +func RecordNonApproved() { + setIndicator(indicatorFalse) +} diff --git a/crypto/internal/fips140/mlkem/cast.go b/crypto/internal/fips140/mlkem/cast.go new file mode 100644 index 00000000000..d1a458eeaa3 --- /dev/null +++ b/crypto/internal/fips140/mlkem/cast.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mlkem + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + fips140.CAST("ML-KEM-768", func() error { + var d = &[32]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + var z = &[32]byte{ + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + } + var m = &[32]byte{ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + } + var K = []byte{ + 0x55, 0x01, 0xfc, 0x52, 0x3b, 0x74, 0x5f, 0x41, + 0x76, 0x2a, 0x18, 0x8d, 0xe4, 0x4a, 0x59, 0xb9, + 0x20, 0xf4, 0x30, 0x14, 0x62, 0x04, 0xee, 0x4e, + 0x79, 0x37, 0x32, 0x39, 0x6d, 0xf7, 0xaa, 0x48, + } + dk := &DecapsulationKey768{} + kemKeyGen(dk, d, z) + ek := dk.EncapsulationKey() + Ke, c := ek.EncapsulateInternal(m) + Kd, err := dk.Decapsulate(c) + if err != nil { + return err + } + if !bytes.Equal(Ke, K) || !bytes.Equal(Kd, K) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/mlkem/field.go b/crypto/internal/fips140/mlkem/field.go new file mode 100644 index 00000000000..007d87ea0e6 --- /dev/null +++ b/crypto/internal/fips140/mlkem/field.go @@ -0,0 +1,551 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mlkem + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// fieldElement is an integer modulo q, an element of ℤ_q. It is always reduced. +type fieldElement uint16 + +// fieldCheckReduced checks that a value a is < q. +func fieldCheckReduced(a uint16) (fieldElement, error) { + if a >= q { + return 0, errors.New("unreduced field element") + } + return fieldElement(a), nil +} + +// fieldReduceOnce reduces a value a < 2q. +func fieldReduceOnce(a uint16) fieldElement { + x := a - q + // If x underflowed, then x >= 2¹⁶ - q > 2¹⁵, so the top bit is set. + x += (x >> 15) * q + return fieldElement(x) +} + +func fieldAdd(a, b fieldElement) fieldElement { + x := uint16(a + b) + return fieldReduceOnce(x) +} + +func fieldSub(a, b fieldElement) fieldElement { + x := uint16(a - b + q) + return fieldReduceOnce(x) +} + +const ( + barrettMultiplier = 5039 // 2¹² * 2¹² / q + barrettShift = 24 // log₂(2¹² * 2¹²) +) + +// fieldReduce reduces a value a < 2q² using Barrett reduction, to avoid +// potentially variable-time division. +func fieldReduce(a uint32) fieldElement { + quotient := uint32((uint64(a) * barrettMultiplier) >> barrettShift) + return fieldReduceOnce(uint16(a - quotient*q)) +} + +func fieldMul(a, b fieldElement) fieldElement { + x := uint32(a) * uint32(b) + return fieldReduce(x) +} + +// fieldMulSub returns a * (b - c). This operation is fused to save a +// fieldReduceOnce after the subtraction. +func fieldMulSub(a, b, c fieldElement) fieldElement { + x := uint32(a) * uint32(b-c+q) + return fieldReduce(x) +} + +// fieldAddMul returns a * b + c * d. This operation is fused to save a +// fieldReduceOnce and a fieldReduce. +func fieldAddMul(a, b, c, d fieldElement) fieldElement { + x := uint32(a) * uint32(b) + x += uint32(c) * uint32(d) + return fieldReduce(x) +} + +// compress maps a field element uniformly to the range 0 to 2ᵈ-1, according to +// FIPS 203, Definition 4.7. +func compress(x fieldElement, d uint8) uint16 { + // We want to compute (x * 2ᵈ) / q, rounded to nearest integer, with 1/2 + // rounding up (see FIPS 203, Section 2.3). + + // Barrett reduction produces a quotient and a remainder in the range [0, 2q), + // such that dividend = quotient * q + remainder. + dividend := uint32(x) << d // x * 2ᵈ + quotient := uint32(uint64(dividend) * barrettMultiplier >> barrettShift) + remainder := dividend - quotient*q + + // Since the remainder is in the range [0, 2q), not [0, q), we need to + // portion it into three spans for rounding. + // + // [ 0, q/2 ) -> round to 0 + // [ q/2, q + q/2 ) -> round to 1 + // [ q + q/2, 2q ) -> round to 2 + // + // We can convert that to the following logic: add 1 if remainder > q/2, + // then add 1 again if remainder > q + q/2. + // + // Note that if remainder > x, then ⌊x⌋ - remainder underflows, and the top + // bit of the difference will be set. + quotient += (q/2 - remainder) >> 31 & 1 + quotient += (q + q/2 - remainder) >> 31 & 1 + + // quotient might have overflowed at this point, so reduce it by masking. + var mask uint32 = (1 << d) - 1 + return uint16(quotient & mask) +} + +// decompress maps a number x between 0 and 2ᵈ-1 uniformly to the full range of +// field elements, according to FIPS 203, Definition 4.8. +func decompress(y uint16, d uint8) fieldElement { + // We want to compute (y * q) / 2ᵈ, rounded to nearest integer, with 1/2 + // rounding up (see FIPS 203, Section 2.3). + + dividend := uint32(y) * q + quotient := dividend >> d // (y * q) / 2ᵈ + + // The d'th least-significant bit of the dividend (the most significant bit + // of the remainder) is 1 for the top half of the values that divide to the + // same quotient, which are the ones that round up. + quotient += dividend >> (d - 1) & 1 + + // quotient is at most (2¹¹-1) * q / 2¹¹ + 1 = 3328, so it didn't overflow. + return fieldElement(quotient) +} + +// ringElement is a polynomial, an element of R_q, represented as an array +// according to FIPS 203, Section 2.4.4. +type ringElement [n]fieldElement + +// polyAdd adds two ringElements or nttElements. +func polyAdd[T ~[n]fieldElement](a, b T) (s T) { + for i := range s { + s[i] = fieldAdd(a[i], b[i]) + } + return s +} + +// polySub subtracts two ringElements or nttElements. +func polySub[T ~[n]fieldElement](a, b T) (s T) { + for i := range s { + s[i] = fieldSub(a[i], b[i]) + } + return s +} + +// polyByteEncode appends the 384-byte encoding of f to b. +// +// It implements ByteEncode₁₂, according to FIPS 203, Algorithm 5. +func polyByteEncode[T ~[n]fieldElement](b []byte, f T) []byte { + out, B := sliceForAppend(b, encodingSize12) + for i := 0; i < n; i += 2 { + x := uint32(f[i]) | uint32(f[i+1])<<12 + B[0] = uint8(x) + B[1] = uint8(x >> 8) + B[2] = uint8(x >> 16) + B = B[3:] + } + return out +} + +// polyByteDecode decodes the 384-byte encoding of a polynomial, checking that +// all the coefficients are properly reduced. This fulfills the "Modulus check" +// step of ML-KEM Encapsulation. +// +// It implements ByteDecode₁₂, according to FIPS 203, Algorithm 6. +func polyByteDecode[T ~[n]fieldElement](b []byte) (T, error) { + if len(b) != encodingSize12 { + return T{}, errors.New("mlkem: invalid encoding length") + } + var f T + for i := 0; i < n; i += 2 { + d := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 + const mask12 = 0b1111_1111_1111 + var err error + if f[i], err = fieldCheckReduced(uint16(d & mask12)); err != nil { + return T{}, errors.New("mlkem: invalid polynomial encoding") + } + if f[i+1], err = fieldCheckReduced(uint16(d >> 12)); err != nil { + return T{}, errors.New("mlkem: invalid polynomial encoding") + } + b = b[3:] + } + return f, nil +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// ringCompressAndEncode1 appends a 32-byte encoding of a ring element to s, +// compressing one coefficients per bit. +// +// It implements Compress₁, according to FIPS 203, Definition 4.7, +// followed by ByteEncode₁, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode1(s []byte, f ringElement) []byte { + s, b := sliceForAppend(s, encodingSize1) + for i := range b { + b[i] = 0 + } + for i := range f { + b[i/8] |= uint8(compress(f[i], 1) << (i % 8)) + } + return s +} + +// ringDecodeAndDecompress1 decodes a 32-byte slice to a ring element where each +// bit is mapped to 0 or ⌈q/2⌋. +// +// It implements ByteDecode₁, according to FIPS 203, Algorithm 6, +// followed by Decompress₁, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress1(b *[encodingSize1]byte) ringElement { + var f ringElement + for i := range f { + b_i := b[i/8] >> (i % 8) & 1 + const halfQ = (q + 1) / 2 // ⌈q/2⌋, rounded up per FIPS 203, Section 2.3 + f[i] = fieldElement(b_i) * halfQ // 0 decompresses to 0, and 1 to ⌈q/2⌋ + } + return f +} + +// ringCompressAndEncode4 appends a 128-byte encoding of a ring element to s, +// compressing two coefficients per byte. +// +// It implements Compress₄, according to FIPS 203, Definition 4.7, +// followed by ByteEncode₄, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode4(s []byte, f ringElement) []byte { + s, b := sliceForAppend(s, encodingSize4) + for i := 0; i < n; i += 2 { + b[i/2] = uint8(compress(f[i], 4) | compress(f[i+1], 4)<<4) + } + return s +} + +// ringDecodeAndDecompress4 decodes a 128-byte encoding of a ring element where +// each four bits are mapped to an equidistant distribution. +// +// It implements ByteDecode₄, according to FIPS 203, Algorithm 6, +// followed by Decompress₄, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress4(b *[encodingSize4]byte) ringElement { + var f ringElement + for i := 0; i < n; i += 2 { + f[i] = fieldElement(decompress(uint16(b[i/2]&0b1111), 4)) + f[i+1] = fieldElement(decompress(uint16(b[i/2]>>4), 4)) + } + return f +} + +// ringCompressAndEncode10 appends a 320-byte encoding of a ring element to s, +// compressing four coefficients per five bytes. +// +// It implements Compress₁₀, according to FIPS 203, Definition 4.7, +// followed by ByteEncode₁₀, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode10(s []byte, f ringElement) []byte { + s, b := sliceForAppend(s, encodingSize10) + for i := 0; i < n; i += 4 { + var x uint64 + x |= uint64(compress(f[i], 10)) + x |= uint64(compress(f[i+1], 10)) << 10 + x |= uint64(compress(f[i+2], 10)) << 20 + x |= uint64(compress(f[i+3], 10)) << 30 + b[0] = uint8(x) + b[1] = uint8(x >> 8) + b[2] = uint8(x >> 16) + b[3] = uint8(x >> 24) + b[4] = uint8(x >> 32) + b = b[5:] + } + return s +} + +// ringDecodeAndDecompress10 decodes a 320-byte encoding of a ring element where +// each ten bits are mapped to an equidistant distribution. +// +// It implements ByteDecode₁₀, according to FIPS 203, Algorithm 6, +// followed by Decompress₁₀, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress10(bb *[encodingSize10]byte) ringElement { + b := bb[:] + var f ringElement + for i := 0; i < n; i += 4 { + x := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 + b = b[5:] + f[i] = fieldElement(decompress(uint16(x>>0&0b11_1111_1111), 10)) + f[i+1] = fieldElement(decompress(uint16(x>>10&0b11_1111_1111), 10)) + f[i+2] = fieldElement(decompress(uint16(x>>20&0b11_1111_1111), 10)) + f[i+3] = fieldElement(decompress(uint16(x>>30&0b11_1111_1111), 10)) + } + return f +} + +// ringCompressAndEncode appends an encoding of a ring element to s, +// compressing each coefficient to d bits. +// +// It implements Compress, according to FIPS 203, Definition 4.7, +// followed by ByteEncode, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode(s []byte, f ringElement, d uint8) []byte { + var b byte + var bIdx uint8 + for i := 0; i < n; i++ { + c := compress(f[i], d) + var cIdx uint8 + for cIdx < d { + b |= byte(c>>cIdx) << bIdx + bits := min(8-bIdx, d-cIdx) + bIdx += bits + cIdx += bits + if bIdx == 8 { + s = append(s, b) + b = 0 + bIdx = 0 + } + } + } + if bIdx != 0 { + panic("mlkem: internal error: bitsFilled != 0") + } + return s +} + +// ringDecodeAndDecompress decodes an encoding of a ring element where +// each d bits are mapped to an equidistant distribution. +// +// It implements ByteDecode, according to FIPS 203, Algorithm 6, +// followed by Decompress, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress(b []byte, d uint8) ringElement { + var f ringElement + var bIdx uint8 + for i := 0; i < n; i++ { + var c uint16 + var cIdx uint8 + for cIdx < d { + c |= uint16(b[0]>>bIdx) << cIdx + c &= (1 << d) - 1 + bits := min(8-bIdx, d-cIdx) + bIdx += bits + cIdx += bits + if bIdx == 8 { + b = b[1:] + bIdx = 0 + } + } + f[i] = fieldElement(decompress(c, d)) + } + if len(b) != 0 { + panic("mlkem: internal error: leftover bytes") + } + return f +} + +// ringCompressAndEncode5 appends a 160-byte encoding of a ring element to s, +// compressing eight coefficients per five bytes. +// +// It implements Compress₅, according to FIPS 203, Definition 4.7, +// followed by ByteEncode₅, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode5(s []byte, f ringElement) []byte { + return ringCompressAndEncode(s, f, 5) +} + +// ringDecodeAndDecompress5 decodes a 160-byte encoding of a ring element where +// each five bits are mapped to an equidistant distribution. +// +// It implements ByteDecode₅, according to FIPS 203, Algorithm 6, +// followed by Decompress₅, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress5(bb *[encodingSize5]byte) ringElement { + return ringDecodeAndDecompress(bb[:], 5) +} + +// ringCompressAndEncode11 appends a 352-byte encoding of a ring element to s, +// compressing eight coefficients per eleven bytes. +// +// It implements Compress₁₁, according to FIPS 203, Definition 4.7, +// followed by ByteEncode₁₁, according to FIPS 203, Algorithm 5. +func ringCompressAndEncode11(s []byte, f ringElement) []byte { + return ringCompressAndEncode(s, f, 11) +} + +// ringDecodeAndDecompress11 decodes a 352-byte encoding of a ring element where +// each eleven bits are mapped to an equidistant distribution. +// +// It implements ByteDecode₁₁, according to FIPS 203, Algorithm 6, +// followed by Decompress₁₁, according to FIPS 203, Definition 4.8. +func ringDecodeAndDecompress11(bb *[encodingSize11]byte) ringElement { + return ringDecodeAndDecompress(bb[:], 11) +} + +// samplePolyCBD draws a ringElement from the special Dη distribution given a +// stream of random bytes generated by the PRF function, according to FIPS 203, +// Algorithm 8 and Definition 4.3. +func samplePolyCBD(s []byte, b byte) ringElement { + prf := sha3.NewShake256() + prf.Write(s) + prf.Write([]byte{b}) + B := make([]byte, 64*2) // η = 2 + prf.Read(B) + + // SamplePolyCBD simply draws four (2η) bits for each coefficient, and adds + // the first two and subtracts the last two. + + var f ringElement + for i := 0; i < n; i += 2 { + b := B[i/2] + b_7, b_6, b_5, b_4 := b>>7, b>>6&1, b>>5&1, b>>4&1 + b_3, b_2, b_1, b_0 := b>>3&1, b>>2&1, b>>1&1, b&1 + f[i] = fieldSub(fieldElement(b_0+b_1), fieldElement(b_2+b_3)) + f[i+1] = fieldSub(fieldElement(b_4+b_5), fieldElement(b_6+b_7)) + } + return f +} + +// nttElement is an NTT representation, an element of T_q, represented as an +// array according to FIPS 203, Section 2.4.4. +type nttElement [n]fieldElement + +// gammas are the values ζ^2BitRev7(i)+1 mod q for each index i, according to +// FIPS 203, Appendix A (with negative values reduced to positive). +var gammas = [128]fieldElement{17, 3312, 2761, 568, 583, 2746, 2649, 680, 1637, 1692, 723, 2606, 2288, 1041, 1100, 2229, 1409, 1920, 2662, 667, 3281, 48, 233, 3096, 756, 2573, 2156, 1173, 3015, 314, 3050, 279, 1703, 1626, 1651, 1678, 2789, 540, 1789, 1540, 1847, 1482, 952, 2377, 1461, 1868, 2687, 642, 939, 2390, 2308, 1021, 2437, 892, 2388, 941, 733, 2596, 2337, 992, 268, 3061, 641, 2688, 1584, 1745, 2298, 1031, 2037, 1292, 3220, 109, 375, 2954, 2549, 780, 2090, 1239, 1645, 1684, 1063, 2266, 319, 3010, 2773, 556, 757, 2572, 2099, 1230, 561, 2768, 2466, 863, 2594, 735, 2804, 525, 1092, 2237, 403, 2926, 1026, 2303, 1143, 2186, 2150, 1179, 2775, 554, 886, 2443, 1722, 1607, 1212, 2117, 1874, 1455, 1029, 2300, 2110, 1219, 2935, 394, 885, 2444, 2154, 1175} + +// nttMul multiplies two nttElements. +// +// It implements MultiplyNTTs, according to FIPS 203, Algorithm 11. +func nttMul(f, g nttElement) nttElement { + var h nttElement + // We use i += 2 for bounds check elimination. See https://go.dev/issue/66826. + for i := 0; i < 256; i += 2 { + a0, a1 := f[i], f[i+1] + b0, b1 := g[i], g[i+1] + h[i] = fieldAddMul(a0, b0, fieldMul(a1, b1), gammas[i/2]) + h[i+1] = fieldAddMul(a0, b1, a1, b0) + } + return h +} + +// zetas are the values ζ^BitRev7(k) mod q for each index k, according to FIPS +// 203, Appendix A. +var zetas = [128]fieldElement{1, 1729, 2580, 3289, 2642, 630, 1897, 848, 1062, 1919, 193, 797, 2786, 3260, 569, 1746, 296, 2447, 1339, 1476, 3046, 56, 2240, 1333, 1426, 2094, 535, 2882, 2393, 2879, 1974, 821, 289, 331, 3253, 1756, 1197, 2304, 2277, 2055, 650, 1977, 2513, 632, 2865, 33, 1320, 1915, 2319, 1435, 807, 452, 1438, 2868, 1534, 2402, 2647, 2617, 1481, 648, 2474, 3110, 1227, 910, 17, 2761, 583, 2649, 1637, 723, 2288, 1100, 1409, 2662, 3281, 233, 756, 2156, 3015, 3050, 1703, 1651, 2789, 1789, 1847, 952, 1461, 2687, 939, 2308, 2437, 2388, 733, 2337, 268, 641, 1584, 2298, 2037, 3220, 375, 2549, 2090, 1645, 1063, 319, 2773, 757, 2099, 561, 2466, 2594, 2804, 1092, 403, 1026, 1143, 2150, 2775, 886, 1722, 1212, 1874, 1029, 2110, 2935, 885, 2154} + +// ntt maps a ringElement to its nttElement representation. +// +// It implements NTT, according to FIPS 203, Algorithm 9. +func ntt(f ringElement) nttElement { + k := 1 + for len := 128; len >= 2; len /= 2 { + for start := 0; start < 256; start += 2 * len { + zeta := zetas[k] + k++ + // Bounds check elimination hint. + f, flen := f[start:start+len], f[start+len:start+len+len] + for j := 0; j < len; j++ { + t := fieldMul(zeta, flen[j]) + flen[j] = fieldSub(f[j], t) + f[j] = fieldAdd(f[j], t) + } + } + } + return nttElement(f) +} + +// inverseNTT maps a nttElement back to the ringElement it represents. +// +// It implements NTT⁻¹, according to FIPS 203, Algorithm 10. +func inverseNTT(f nttElement) ringElement { + k := 127 + for len := 2; len <= 128; len *= 2 { + for start := 0; start < 256; start += 2 * len { + zeta := zetas[k] + k-- + // Bounds check elimination hint. + f, flen := f[start:start+len], f[start+len:start+len+len] + for j := 0; j < len; j++ { + t := f[j] + f[j] = fieldAdd(t, flen[j]) + flen[j] = fieldMulSub(zeta, flen[j], t) + } + } + } + for i := range f { + f[i] = fieldMul(f[i], 3303) // 3303 = 128⁻¹ mod q + } + return ringElement(f) +} + +// sampleNTT draws a uniformly random nttElement from a stream of uniformly +// random bytes generated by the XOF function, according to FIPS 203, +// Algorithm 7. +func sampleNTT(rho []byte, ii, jj byte) nttElement { + B := sha3.NewShake128() + B.Write(rho) + B.Write([]byte{ii, jj}) + + // SampleNTT essentially draws 12 bits at a time from r, interprets them in + // little-endian, and rejects values higher than q, until it drew 256 + // values. (The rejection rate is approximately 19%.) + // + // To do this from a bytes stream, it draws three bytes at a time, and + // splits them into two uint16 appropriately masked. + // + // r₀ r₁ r₂ + // |- - - - - - - -|- - - - - - - -|- - - - - - - -| + // + // Uint16(r₀ || r₁) + // |- - - - - - - - - - - - - - - -| + // |- - - - - - - - - - - -| + // d₁ + // + // Uint16(r₁ || r₂) + // |- - - - - - - - - - - - - - - -| + // |- - - - - - - - - - - -| + // d₂ + // + // Note that in little-endian, the rightmost bits are the most significant + // bits (dropped with a mask) and the leftmost bits are the least + // significant bits (dropped with a right shift). + + var a nttElement + var j int // index into a + var buf [24]byte // buffered reads from B + off := len(buf) // index into buf, starts in a "buffer fully consumed" state + for { + if off >= len(buf) { + B.Read(buf[:]) + off = 0 + } + d1 := byteorder.LEUint16(buf[off:]) & 0b1111_1111_1111 + d2 := byteorder.LEUint16(buf[off+1:]) >> 4 + off += 3 + if d1 < q { + a[j] = fieldElement(d1) + j++ + } + if j >= len(a) { + break + } + if d2 < q { + a[j] = fieldElement(d2) + j++ + } + if j >= len(a) { + break + } + } + return a +} diff --git a/crypto/internal/fips140/mlkem/field_test.go b/crypto/internal/fips140/mlkem/field_test.go new file mode 100644 index 00000000000..3a6d983803c --- /dev/null +++ b/crypto/internal/fips140/mlkem/field_test.go @@ -0,0 +1,269 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mlkem + +import ( + "bytes" + "crypto/rand" + "math/big" + mathrand "math/rand/v2" + "strconv" + "testing" +) + +func TestFieldReduce(t *testing.T) { + for a := uint32(0); a < 2*q*q; a++ { + got := fieldReduce(a) + exp := fieldElement(a % q) + if got != exp { + t.Fatalf("reduce(%d) = %d, expected %d", a, got, exp) + } + } +} + +func TestFieldAdd(t *testing.T) { + for a := fieldElement(0); a < q; a++ { + for b := fieldElement(0); b < q; b++ { + got := fieldAdd(a, b) + exp := (a + b) % q + if got != exp { + t.Fatalf("%d + %d = %d, expected %d", a, b, got, exp) + } + } + } +} + +func TestFieldSub(t *testing.T) { + for a := fieldElement(0); a < q; a++ { + for b := fieldElement(0); b < q; b++ { + got := fieldSub(a, b) + exp := (a - b + q) % q + if got != exp { + t.Fatalf("%d - %d = %d, expected %d", a, b, got, exp) + } + } + } +} + +func TestFieldMul(t *testing.T) { + for a := fieldElement(0); a < q; a++ { + for b := fieldElement(0); b < q; b++ { + got := fieldMul(a, b) + exp := fieldElement((uint32(a) * uint32(b)) % q) + if got != exp { + t.Fatalf("%d * %d = %d, expected %d", a, b, got, exp) + } + } + } +} + +func TestDecompressCompress(t *testing.T) { + for _, bits := range []uint8{1, 4, 10} { + for a := uint16(0); a < 1<= q { + t.Fatalf("decompress(%d, %d) = %d >= q", a, bits, f) + } + got := compress(f, bits) + if got != a { + t.Fatalf("compress(decompress(%d, %d), %d) = %d", a, bits, bits, got) + } + } + + for a := fieldElement(0); a < q; a++ { + c := compress(a, bits) + if c >= 1<= 2^bits", a, bits, c) + } + got := decompress(c, bits) + diff := min(a-got, got-a, a-got+q, got-a+q) + ceil := q / (1 << bits) + if diff > fieldElement(ceil) { + t.Fatalf("decompress(compress(%d, %d), %d) = %d (diff %d, max diff %d)", + a, bits, bits, got, diff, ceil) + } + } + } +} + +func CompressRat(x fieldElement, d uint8) uint16 { + if x >= q { + panic("x out of range") + } + if d <= 0 || d >= 12 { + panic("d out of range") + } + + precise := big.NewRat((1<= 1<= 12 { + panic("d out of range") + } + + precise := big.NewRat(q*int64(y), 1<>7 != 0 { + panic("not 7 bits") + } + var r uint8 + r |= n >> 6 & 0b0000_0001 + r |= n >> 4 & 0b0000_0010 + r |= n >> 2 & 0b0000_0100 + r |= n /**/ & 0b0000_1000 + r |= n << 2 & 0b0001_0000 + r |= n << 4 & 0b0010_0000 + r |= n << 6 & 0b0100_0000 + return r +} + +func TestZetas(t *testing.T) { + ζ := big.NewInt(17) + q := big.NewInt(q) + for k, zeta := range zetas { + // ζ^BitRev7(k) mod q + exp := new(big.Int).Exp(ζ, big.NewInt(int64(BitRev7(uint8(k)))), q) + if big.NewInt(int64(zeta)).Cmp(exp) != 0 { + t.Errorf("zetas[%d] = %v, expected %v", k, zeta, exp) + } + } +} + +func TestGammas(t *testing.T) { + ζ := big.NewInt(17) + q := big.NewInt(q) + for k, gamma := range gammas { + // ζ^2BitRev7(i)+1 + exp := new(big.Int).Exp(ζ, big.NewInt(int64(BitRev7(uint8(k)))*2+1), q) + if big.NewInt(int64(gamma)).Cmp(exp) != 0 { + t.Errorf("gammas[%d] = %v, expected %v", k, gamma, exp) + } + } +} diff --git a/crypto/internal/fips140/mlkem/generate1024.go b/crypto/internal/fips140/mlkem/generate1024.go new file mode 100644 index 00000000000..9e38ad00df9 --- /dev/null +++ b/crypto/internal/fips140/mlkem/generate1024.go @@ -0,0 +1,128 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import ( + "flag" + "go/ast" + "go/format" + "go/parser" + "go/token" + "log" + "os" + "strings" +) + +var replacements = map[string]string{ + "k": "k1024", + + "CiphertextSize768": "CiphertextSize1024", + "EncapsulationKeySize768": "EncapsulationKeySize1024", + "decapsulationKeySize768": "decapsulationKeySize1024", + + "encryptionKey": "encryptionKey1024", + "decryptionKey": "decryptionKey1024", + + "EncapsulationKey768": "EncapsulationKey1024", + "NewEncapsulationKey768": "NewEncapsulationKey1024", + "parseEK": "parseEK1024", + + "kemEncaps": "kemEncaps1024", + "pkeEncrypt": "pkeEncrypt1024", + + "DecapsulationKey768": "DecapsulationKey1024", + "NewDecapsulationKey768": "NewDecapsulationKey1024", + "TestingOnlyNewDecapsulationKey768": "TestingOnlyNewDecapsulationKey1024", + "newKeyFromSeed": "newKeyFromSeed1024", + "TestingOnlyExpandedBytes768": "TestingOnlyExpandedBytes1024", + + "kemDecaps": "kemDecaps1024", + "pkeDecrypt": "pkeDecrypt1024", + + "GenerateKey768": "GenerateKey1024", + "GenerateKeyInternal768": "GenerateKeyInternal1024", + "generateKey": "generateKey1024", + + "kemKeyGen": "kemKeyGen1024", + "kemPCT": "kemPCT1024", + + "encodingSize4": "encodingSize5", + "encodingSize10": "encodingSize11", + "ringCompressAndEncode4": "ringCompressAndEncode5", + "ringCompressAndEncode10": "ringCompressAndEncode11", + "ringDecodeAndDecompress4": "ringDecodeAndDecompress5", + "ringDecodeAndDecompress10": "ringDecodeAndDecompress11", +} + +func main() { + inputFile := flag.String("input", "", "") + outputFile := flag.String("output", "", "") + flag.Parse() + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, *inputFile, nil, parser.SkipObjectResolution|parser.ParseComments) + if err != nil { + log.Fatal(err) + } + cmap := ast.NewCommentMap(fset, f, f.Comments) + + // Drop header comments. + cmap[ast.Node(f)] = nil + + // Remove top-level consts used across the main and generated files. + var newDecls []ast.Decl + for _, decl := range f.Decls { + switch d := decl.(type) { + case *ast.GenDecl: + if d.Tok == token.CONST { + continue // Skip const declarations + } + if d.Tok == token.IMPORT { + cmap[decl] = nil // Drop pre-import comments. + } + } + newDecls = append(newDecls, decl) + } + f.Decls = newDecls + + // Replace identifiers. + ast.Inspect(f, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.Ident: + if replacement, ok := replacements[x.Name]; ok { + x.Name = replacement + } + } + return true + }) + + // Replace identifiers in comments. + for _, c := range f.Comments { + for _, l := range c.List { + for k, v := range replacements { + if k == "k" { + continue + } + l.Text = strings.ReplaceAll(l.Text, k, v) + } + } + } + + out, err := os.Create(*outputFile) + if err != nil { + log.Fatal(err) + } + defer out.Close() + + out.WriteString("// Code generated by generate1024.go. DO NOT EDIT.\n\n") + + f.Comments = cmap.Filter(f).Comments() + err = format.Node(out, fset, f) + if err != nil { + log.Fatal(err) + } +} diff --git a/crypto/internal/fips140/mlkem/mlkem1024.go b/crypto/internal/fips140/mlkem/mlkem1024.go new file mode 100644 index 00000000000..4b5dd803cb0 --- /dev/null +++ b/crypto/internal/fips140/mlkem/mlkem1024.go @@ -0,0 +1,458 @@ +// Code generated by generate1024.go. DO NOT EDIT. + +package mlkem + +import ( + "bytes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "errors" +) + +// A DecapsulationKey1024 is the secret key used to decapsulate a shared key from a +// ciphertext. It includes various precomputed values. +type DecapsulationKey1024 struct { + d [32]byte // decapsulation key seed + z [32]byte // implicit rejection sampling seed + + ρ [32]byte // sampleNTT seed for A, stored for the encapsulation key + h [32]byte // H(ek), stored for ML-KEM.Decaps_internal + + encryptionKey1024 + decryptionKey1024 +} + +// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form. +// +// The decapsulation key must be kept secret. +func (dk *DecapsulationKey1024) Bytes() []byte { + var b [SeedSize]byte + copy(b[:], dk.d[:]) + copy(b[32:], dk.z[:]) + return b[:] +} + +// TestingOnlyExpandedBytes1024 returns the decapsulation key as a byte slice +// using the full expanded NIST encoding. +// +// This should only be used for ACVP testing. For all other purposes prefer +// the Bytes method that returns the (much smaller) seed. +func TestingOnlyExpandedBytes1024(dk *DecapsulationKey1024) []byte { + b := make([]byte, 0, decapsulationKeySize1024) + + // ByteEncode₁₂(s) + for i := range dk.s { + b = polyByteEncode(b, dk.s[i]) + } + + // ByteEncode₁₂(t) || ρ + for i := range dk.t { + b = polyByteEncode(b, dk.t[i]) + } + b = append(b, dk.ρ[:]...) + + // H(ek) || z + b = append(b, dk.h[:]...) + b = append(b, dk.z[:]...) + + return b +} + +// EncapsulationKey returns the public encapsulation key necessary to produce +// ciphertexts. +func (dk *DecapsulationKey1024) EncapsulationKey() *EncapsulationKey1024 { + return &EncapsulationKey1024{ + ρ: dk.ρ, + h: dk.h, + encryptionKey1024: dk.encryptionKey1024, + } +} + +// An EncapsulationKey1024 is the public key used to produce ciphertexts to be +// decapsulated by the corresponding [DecapsulationKey1024]. +type EncapsulationKey1024 struct { + ρ [32]byte // sampleNTT seed for A + h [32]byte // H(ek) + encryptionKey1024 +} + +// Bytes returns the encapsulation key as a byte slice. +func (ek *EncapsulationKey1024) Bytes() []byte { + // The actual logic is in a separate function to outline this allocation. + b := make([]byte, 0, EncapsulationKeySize1024) + return ek.bytes(b) +} + +func (ek *EncapsulationKey1024) bytes(b []byte) []byte { + for i := range ek.t { + b = polyByteEncode(b, ek.t[i]) + } + b = append(b, ek.ρ[:]...) + return b +} + +// encryptionKey1024 is the parsed and expanded form of a PKE encryption key. +type encryptionKey1024 struct { + t [k1024]nttElement // ByteDecode₁₂(ek[:384k]) + a [k1024 * k1024]nttElement // A[i*k+j] = sampleNTT(ρ, j, i) +} + +// decryptionKey1024 is the parsed and expanded form of a PKE decryption key. +type decryptionKey1024 struct { + s [k1024]nttElement // ByteDecode₁₂(dk[:decryptionKey1024Size]) +} + +// GenerateKey1024 generates a new decapsulation key, drawing random bytes from +// a DRBG. The decapsulation key must be kept secret. +func GenerateKey1024() (*DecapsulationKey1024, error) { + // The actual logic is in a separate function to outline this allocation. + dk := &DecapsulationKey1024{} + return generateKey1024(dk) +} + +func generateKey1024(dk *DecapsulationKey1024) (*DecapsulationKey1024, error) { + var d [32]byte + drbg.Read(d[:]) + var z [32]byte + drbg.Read(z[:]) + kemKeyGen1024(dk, &d, &z) + if err := fips140.PCT("ML-KEM PCT", func() error { return kemPCT1024(dk) }); err != nil { + // This clearly can't happen, but FIPS 140-3 requires us to check. + panic(err) + } + fips140.RecordApproved() + return dk, nil +} + +// GenerateKeyInternal1024 is a derandomized version of GenerateKey1024, +// exclusively for use in tests. +func GenerateKeyInternal1024(d, z *[32]byte) *DecapsulationKey1024 { + dk := &DecapsulationKey1024{} + kemKeyGen1024(dk, d, z) + return dk +} + +// NewDecapsulationKey1024 parses a decapsulation key from a 64-byte +// seed in the "d || z" form. The seed must be uniformly random. +func NewDecapsulationKey1024(seed []byte) (*DecapsulationKey1024, error) { + // The actual logic is in a separate function to outline this allocation. + dk := &DecapsulationKey1024{} + return newKeyFromSeed1024(dk, seed) +} + +func newKeyFromSeed1024(dk *DecapsulationKey1024, seed []byte) (*DecapsulationKey1024, error) { + if len(seed) != SeedSize { + return nil, errors.New("mlkem: invalid seed length") + } + d := (*[32]byte)(seed[:32]) + z := (*[32]byte)(seed[32:]) + kemKeyGen1024(dk, d, z) + if err := fips140.PCT("ML-KEM PCT", func() error { return kemPCT1024(dk) }); err != nil { + // This clearly can't happen, but FIPS 140-3 requires us to check. + panic(err) + } + fips140.RecordApproved() + return dk, nil +} + +// TestingOnlyNewDecapsulationKey1024 parses a decapsulation key from its expanded NIST format. +// +// Bytes() must not be called on the returned key, as it will not produce the +// original seed. +// +// This function should only be used for ACVP testing. Prefer NewDecapsulationKey1024 for all +// other purposes. +func TestingOnlyNewDecapsulationKey1024(b []byte) (*DecapsulationKey1024, error) { + if len(b) != decapsulationKeySize1024 { + return nil, errors.New("mlkem: invalid NIST decapsulation key length") + } + + dk := &DecapsulationKey1024{} + for i := range dk.s { + var err error + dk.s[i], err = polyByteDecode[nttElement](b[:encodingSize12]) + if err != nil { + return nil, errors.New("mlkem: invalid secret key encoding") + } + b = b[encodingSize12:] + } + + ek, err := NewEncapsulationKey1024(b[:EncapsulationKeySize1024]) + if err != nil { + return nil, err + } + dk.ρ = ek.ρ + dk.h = ek.h + dk.encryptionKey1024 = ek.encryptionKey1024 + b = b[EncapsulationKeySize1024:] + + if !bytes.Equal(dk.h[:], b[:32]) { + return nil, errors.New("mlkem: inconsistent H(ek) in encoded bytes") + } + b = b[32:] + + copy(dk.z[:], b) + + // Generate a random d value for use in Bytes(). This is a safety mechanism + // that avoids returning a broken key vs a random key if this function is + // called in contravention of the TestingOnlyNewDecapsulationKey1024 function + // comment advising against it. + drbg.Read(dk.d[:]) + + return dk, nil +} + +// kemKeyGen1024 generates a decapsulation key. +// +// It implements ML-KEM.KeyGen_internal according to FIPS 203, Algorithm 16, and +// K-PKE.KeyGen according to FIPS 203, Algorithm 13. The two are merged to save +// copies and allocations. +func kemKeyGen1024(dk *DecapsulationKey1024, d, z *[32]byte) { + dk.d = *d + dk.z = *z + + g := sha3.New512() + g.Write(d[:]) + g.Write([]byte{k1024}) // Module dimension as a domain separator. + G := g.Sum(make([]byte, 0, 64)) + ρ, σ := G[:32], G[32:] + dk.ρ = [32]byte(ρ) + + A := &dk.a + for i := byte(0); i < k1024; i++ { + for j := byte(0); j < k1024; j++ { + A[i*k1024+j] = sampleNTT(ρ, j, i) + } + } + + var N byte + s := &dk.s + for i := range s { + s[i] = ntt(samplePolyCBD(σ, N)) + N++ + } + e := make([]nttElement, k1024) + for i := range e { + e[i] = ntt(samplePolyCBD(σ, N)) + N++ + } + + t := &dk.t + for i := range t { // t = A ◦ s + e + t[i] = e[i] + for j := range s { + t[i] = polyAdd(t[i], nttMul(A[i*k1024+j], s[j])) + } + } + + H := sha3.New256() + ek := dk.EncapsulationKey().Bytes() + H.Write(ek) + H.Sum(dk.h[:0]) +} + +// kemPCT1024 performs a Pairwise Consistency Test per FIPS 140-3 IG 10.3.A +// Additional Comment 1: "For key pairs generated for use with approved KEMs in +// FIPS 203, the PCT shall consist of applying the encapsulation key ek to +// encapsulate a shared secret K leading to ciphertext c, and then applying +// decapsulation key dk to retrieve the same shared secret K. The PCT passes if +// the two shared secret K values are equal. The PCT shall be performed either +// when keys are generated/imported, prior to the first exportation, or prior to +// the first operational use (if not exported before the first use)." +func kemPCT1024(dk *DecapsulationKey1024) error { + ek := dk.EncapsulationKey() + K, c := ek.Encapsulate() + K1, err := dk.Decapsulate(c) + if err != nil { + return err + } + if subtle.ConstantTimeCompare(K, K1) != 1 { + return errors.New("mlkem: PCT failed") + } + return nil +} + +// Encapsulate generates a shared key and an associated ciphertext from an +// encapsulation key, drawing random bytes from a DRBG. +// +// The shared key must be kept secret. +func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { + // The actual logic is in a separate function to outline this allocation. + var cc [CiphertextSize1024]byte + return ek.encapsulate(&cc) +} + +func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (sharedKey, ciphertext []byte) { + var m [messageSize]byte + drbg.Read(m[:]) + // Note that the modulus check (step 2 of the encapsulation key check from + // FIPS 203, Section 7.2) is performed by polyByteDecode in parseEK1024. + fips140.RecordApproved() + return kemEncaps1024(cc, ek, &m) +} + +// EncapsulateInternal is a derandomized version of Encapsulate, exclusively for +// use in tests. +func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { + cc := &[CiphertextSize1024]byte{} + return kemEncaps1024(cc, ek, m) +} + +// kemEncaps1024 generates a shared key and an associated ciphertext. +// +// It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. +func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (K, c []byte) { + g := sha3.New512() + g.Write(m[:]) + g.Write(ek.h[:]) + G := g.Sum(nil) + K, r := G[:SharedKeySize], G[SharedKeySize:] + c = pkeEncrypt1024(cc, &ek.encryptionKey1024, m, r) + return K, c +} + +// NewEncapsulationKey1024 parses an encapsulation key from its encoded form. +// If the encapsulation key is not valid, NewEncapsulationKey1024 returns an error. +func NewEncapsulationKey1024(encapsulationKey []byte) (*EncapsulationKey1024, error) { + // The actual logic is in a separate function to outline this allocation. + ek := &EncapsulationKey1024{} + return parseEK1024(ek, encapsulationKey) +} + +// parseEK1024 parses an encryption key from its encoded form. +// +// It implements the initial stages of K-PKE.Encrypt according to FIPS 203, +// Algorithm 14. +func parseEK1024(ek *EncapsulationKey1024, ekPKE []byte) (*EncapsulationKey1024, error) { + if len(ekPKE) != EncapsulationKeySize1024 { + return nil, errors.New("mlkem: invalid encapsulation key length") + } + + h := sha3.New256() + h.Write(ekPKE) + h.Sum(ek.h[:0]) + + for i := range ek.t { + var err error + ek.t[i], err = polyByteDecode[nttElement](ekPKE[:encodingSize12]) + if err != nil { + return nil, err + } + ekPKE = ekPKE[encodingSize12:] + } + copy(ek.ρ[:], ekPKE) + + for i := byte(0); i < k1024; i++ { + for j := byte(0); j < k1024; j++ { + ek.a[i*k1024+j] = sampleNTT(ek.ρ[:], j, i) + } + } + + return ek, nil +} + +// pkeEncrypt1024 encrypt a plaintext message. +// +// It implements K-PKE.Encrypt according to FIPS 203, Algorithm 14, although the +// computation of t and AT is done in parseEK1024. +func pkeEncrypt1024(cc *[CiphertextSize1024]byte, ex *encryptionKey1024, m *[messageSize]byte, rnd []byte) []byte { + var N byte + r, e1 := make([]nttElement, k1024), make([]ringElement, k1024) + for i := range r { + r[i] = ntt(samplePolyCBD(rnd, N)) + N++ + } + for i := range e1 { + e1[i] = samplePolyCBD(rnd, N) + N++ + } + e2 := samplePolyCBD(rnd, N) + + u := make([]ringElement, k1024) // NTT⁻¹(AT ◦ r) + e1 + for i := range u { + u[i] = e1[i] + for j := range r { + // Note that i and j are inverted, as we need the transposed of A. + u[i] = polyAdd(u[i], inverseNTT(nttMul(ex.a[j*k1024+i], r[j]))) + } + } + + μ := ringDecodeAndDecompress1(m) + + var vNTT nttElement // t⊺ ◦ r + for i := range ex.t { + vNTT = polyAdd(vNTT, nttMul(ex.t[i], r[i])) + } + v := polyAdd(polyAdd(inverseNTT(vNTT), e2), μ) + + c := cc[:0] + for _, f := range u { + c = ringCompressAndEncode11(c, f) + } + c = ringCompressAndEncode5(c, v) + + return c +} + +// Decapsulate generates a shared key from a ciphertext and a decapsulation key. +// If the ciphertext is not valid, Decapsulate returns an error. +// +// The shared key must be kept secret. +func (dk *DecapsulationKey1024) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) { + if len(ciphertext) != CiphertextSize1024 { + return nil, errors.New("mlkem: invalid ciphertext length") + } + c := (*[CiphertextSize1024]byte)(ciphertext) + // Note that the hash check (step 3 of the decapsulation input check from + // FIPS 203, Section 7.3) is foregone as a DecapsulationKey is always + // validly generated by ML-KEM.KeyGen_internal. + return kemDecaps1024(dk, c), nil +} + +// kemDecaps1024 produces a shared key from a ciphertext. +// +// It implements ML-KEM.Decaps_internal according to FIPS 203, Algorithm 18. +func kemDecaps1024(dk *DecapsulationKey1024, c *[CiphertextSize1024]byte) (K []byte) { + fips140.RecordApproved() + m := pkeDecrypt1024(&dk.decryptionKey1024, c) + g := sha3.New512() + g.Write(m[:]) + g.Write(dk.h[:]) + G := g.Sum(make([]byte, 0, 64)) + Kprime, r := G[:SharedKeySize], G[SharedKeySize:] + J := sha3.NewShake256() + J.Write(dk.z[:]) + J.Write(c[:]) + Kout := make([]byte, SharedKeySize) + J.Read(Kout) + var cc [CiphertextSize1024]byte + c1 := pkeEncrypt1024(&cc, &dk.encryptionKey1024, (*[32]byte)(m), r) + + subtle.ConstantTimeCopy(subtle.ConstantTimeCompare(c[:], c1), Kout, Kprime) + return Kout +} + +// pkeDecrypt1024 decrypts a ciphertext. +// +// It implements K-PKE.Decrypt according to FIPS 203, Algorithm 15, +// although s is retained from kemKeyGen1024. +func pkeDecrypt1024(dx *decryptionKey1024, c *[CiphertextSize1024]byte) []byte { + u := make([]ringElement, k1024) + for i := range u { + b := (*[encodingSize11]byte)(c[encodingSize11*i : encodingSize11*(i+1)]) + u[i] = ringDecodeAndDecompress11(b) + } + + b := (*[encodingSize5]byte)(c[encodingSize11*k1024:]) + v := ringDecodeAndDecompress5(b) + + var mask nttElement // s⊺ ◦ NTT(u) + for i := range dx.s { + mask = polyAdd(mask, nttMul(dx.s[i], ntt(u[i]))) + } + w := polySub(v, inverseNTT(mask)) + + return ringCompressAndEncode1(nil, w) +} diff --git a/crypto/internal/fips140/mlkem/mlkem768.go b/crypto/internal/fips140/mlkem/mlkem768.go new file mode 100644 index 00000000000..8c6e5dc3b08 --- /dev/null +++ b/crypto/internal/fips140/mlkem/mlkem768.go @@ -0,0 +1,518 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mlkem implements the quantum-resistant key encapsulation method +// ML-KEM (formerly known as Kyber), as specified in [NIST FIPS 203]. +// +// [NIST FIPS 203]: https://doi.org/10.6028/NIST.FIPS.203 +package mlkem + +// This package targets security, correctness, simplicity, readability, and +// reviewability as its primary goals. All critical operations are performed in +// constant time. +// +// Variable and function names, as well as code layout, are selected to +// facilitate reviewing the implementation against the NIST FIPS 203 document. +// +// Reviewers unfamiliar with polynomials or linear algebra might find the +// background at https://words.filippo.io/kyber-math/ useful. +// +// This file implements the recommended parameter set ML-KEM-768. The ML-KEM-1024 +// parameter set implementation is auto-generated from this file. +// +//go:generate go run generate1024.go -input mlkem768.go -output mlkem1024.go + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" +) + +const ( + // ML-KEM global constants. + n = 256 + q = 3329 + + // encodingSizeX is the byte size of a ringElement or nttElement encoded + // by ByteEncode_X (FIPS 203, Algorithm 5). + encodingSize12 = n * 12 / 8 + encodingSize11 = n * 11 / 8 + encodingSize10 = n * 10 / 8 + encodingSize5 = n * 5 / 8 + encodingSize4 = n * 4 / 8 + encodingSize1 = n * 1 / 8 + + messageSize = encodingSize1 + + SharedKeySize = 32 + SeedSize = 32 + 32 +) + +// ML-KEM-768 parameters. +const ( + k = 3 + + CiphertextSize768 = k*encodingSize10 + encodingSize4 + EncapsulationKeySize768 = k*encodingSize12 + 32 + decapsulationKeySize768 = k*encodingSize12 + EncapsulationKeySize768 + 32 + 32 +) + +// ML-KEM-1024 parameters. +const ( + k1024 = 4 + + CiphertextSize1024 = k1024*encodingSize11 + encodingSize5 + EncapsulationKeySize1024 = k1024*encodingSize12 + 32 + decapsulationKeySize1024 = k1024*encodingSize12 + EncapsulationKeySize1024 + 32 + 32 +) + +// A DecapsulationKey768 is the secret key used to decapsulate a shared key from a +// ciphertext. It includes various precomputed values. +type DecapsulationKey768 struct { + d [32]byte // decapsulation key seed + z [32]byte // implicit rejection sampling seed + + ρ [32]byte // sampleNTT seed for A, stored for the encapsulation key + h [32]byte // H(ek), stored for ML-KEM.Decaps_internal + + encryptionKey + decryptionKey +} + +// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form. +// +// The decapsulation key must be kept secret. +func (dk *DecapsulationKey768) Bytes() []byte { + var b [SeedSize]byte + copy(b[:], dk.d[:]) + copy(b[32:], dk.z[:]) + return b[:] +} + +// TestingOnlyExpandedBytes768 returns the decapsulation key as a byte slice +// using the full expanded NIST encoding. +// +// This should only be used for ACVP testing. For all other purposes prefer +// the Bytes method that returns the (much smaller) seed. +func TestingOnlyExpandedBytes768(dk *DecapsulationKey768) []byte { + b := make([]byte, 0, decapsulationKeySize768) + + // ByteEncode₁₂(s) + for i := range dk.s { + b = polyByteEncode(b, dk.s[i]) + } + + // ByteEncode₁₂(t) || ρ + for i := range dk.t { + b = polyByteEncode(b, dk.t[i]) + } + b = append(b, dk.ρ[:]...) + + // H(ek) || z + b = append(b, dk.h[:]...) + b = append(b, dk.z[:]...) + + return b +} + +// EncapsulationKey returns the public encapsulation key necessary to produce +// ciphertexts. +func (dk *DecapsulationKey768) EncapsulationKey() *EncapsulationKey768 { + return &EncapsulationKey768{ + ρ: dk.ρ, + h: dk.h, + encryptionKey: dk.encryptionKey, + } +} + +// An EncapsulationKey768 is the public key used to produce ciphertexts to be +// decapsulated by the corresponding [DecapsulationKey768]. +type EncapsulationKey768 struct { + ρ [32]byte // sampleNTT seed for A + h [32]byte // H(ek) + encryptionKey +} + +// Bytes returns the encapsulation key as a byte slice. +func (ek *EncapsulationKey768) Bytes() []byte { + // The actual logic is in a separate function to outline this allocation. + b := make([]byte, 0, EncapsulationKeySize768) + return ek.bytes(b) +} + +func (ek *EncapsulationKey768) bytes(b []byte) []byte { + for i := range ek.t { + b = polyByteEncode(b, ek.t[i]) + } + b = append(b, ek.ρ[:]...) + return b +} + +// encryptionKey is the parsed and expanded form of a PKE encryption key. +type encryptionKey struct { + t [k]nttElement // ByteDecode₁₂(ek[:384k]) + a [k * k]nttElement // A[i*k+j] = sampleNTT(ρ, j, i) +} + +// decryptionKey is the parsed and expanded form of a PKE decryption key. +type decryptionKey struct { + s [k]nttElement // ByteDecode₁₂(dk[:decryptionKeySize]) +} + +// GenerateKey768 generates a new decapsulation key, drawing random bytes from +// a DRBG. The decapsulation key must be kept secret. +func GenerateKey768() (*DecapsulationKey768, error) { + // The actual logic is in a separate function to outline this allocation. + dk := &DecapsulationKey768{} + return generateKey(dk) +} + +func generateKey(dk *DecapsulationKey768) (*DecapsulationKey768, error) { + var d [32]byte + drbg.Read(d[:]) + var z [32]byte + drbg.Read(z[:]) + kemKeyGen(dk, &d, &z) + if err := fips140.PCT("ML-KEM PCT", func() error { return kemPCT(dk) }); err != nil { + // This clearly can't happen, but FIPS 140-3 requires us to check. + panic(err) + } + fips140.RecordApproved() + return dk, nil +} + +// GenerateKeyInternal768 is a derandomized version of GenerateKey768, +// exclusively for use in tests. +func GenerateKeyInternal768(d, z *[32]byte) *DecapsulationKey768 { + dk := &DecapsulationKey768{} + kemKeyGen(dk, d, z) + return dk +} + +// NewDecapsulationKey768 parses a decapsulation key from a 64-byte +// seed in the "d || z" form. The seed must be uniformly random. +func NewDecapsulationKey768(seed []byte) (*DecapsulationKey768, error) { + // The actual logic is in a separate function to outline this allocation. + dk := &DecapsulationKey768{} + return newKeyFromSeed(dk, seed) +} + +func newKeyFromSeed(dk *DecapsulationKey768, seed []byte) (*DecapsulationKey768, error) { + if len(seed) != SeedSize { + return nil, errors.New("mlkem: invalid seed length") + } + d := (*[32]byte)(seed[:32]) + z := (*[32]byte)(seed[32:]) + kemKeyGen(dk, d, z) + if err := fips140.PCT("ML-KEM PCT", func() error { return kemPCT(dk) }); err != nil { + // This clearly can't happen, but FIPS 140-3 requires us to check. + panic(err) + } + fips140.RecordApproved() + return dk, nil +} + +// TestingOnlyNewDecapsulationKey768 parses a decapsulation key from its expanded NIST format. +// +// Bytes() must not be called on the returned key, as it will not produce the +// original seed. +// +// This function should only be used for ACVP testing. Prefer NewDecapsulationKey768 for all +// other purposes. +func TestingOnlyNewDecapsulationKey768(b []byte) (*DecapsulationKey768, error) { + if len(b) != decapsulationKeySize768 { + return nil, errors.New("mlkem: invalid NIST decapsulation key length") + } + + dk := &DecapsulationKey768{} + for i := range dk.s { + var err error + dk.s[i], err = polyByteDecode[nttElement](b[:encodingSize12]) + if err != nil { + return nil, errors.New("mlkem: invalid secret key encoding") + } + b = b[encodingSize12:] + } + + ek, err := NewEncapsulationKey768(b[:EncapsulationKeySize768]) + if err != nil { + return nil, err + } + dk.ρ = ek.ρ + dk.h = ek.h + dk.encryptionKey = ek.encryptionKey + b = b[EncapsulationKeySize768:] + + if !bytes.Equal(dk.h[:], b[:32]) { + return nil, errors.New("mlkem: inconsistent H(ek) in encoded bytes") + } + b = b[32:] + + copy(dk.z[:], b) + + // Generate a random d value for use in Bytes(). This is a safety mechanism + // that avoids returning a broken key vs a random key if this function is + // called in contravention of the TestingOnlyNewDecapsulationKey768 function + // comment advising against it. + drbg.Read(dk.d[:]) + + return dk, nil +} + +// kemKeyGen generates a decapsulation key. +// +// It implements ML-KEM.KeyGen_internal according to FIPS 203, Algorithm 16, and +// K-PKE.KeyGen according to FIPS 203, Algorithm 13. The two are merged to save +// copies and allocations. +func kemKeyGen(dk *DecapsulationKey768, d, z *[32]byte) { + dk.d = *d + dk.z = *z + + g := sha3.New512() + g.Write(d[:]) + g.Write([]byte{k}) // Module dimension as a domain separator. + G := g.Sum(make([]byte, 0, 64)) + ρ, σ := G[:32], G[32:] + dk.ρ = [32]byte(ρ) + + A := &dk.a + for i := byte(0); i < k; i++ { + for j := byte(0); j < k; j++ { + A[i*k+j] = sampleNTT(ρ, j, i) + } + } + + var N byte + s := &dk.s + for i := range s { + s[i] = ntt(samplePolyCBD(σ, N)) + N++ + } + e := make([]nttElement, k) + for i := range e { + e[i] = ntt(samplePolyCBD(σ, N)) + N++ + } + + t := &dk.t + for i := range t { // t = A ◦ s + e + t[i] = e[i] + for j := range s { + t[i] = polyAdd(t[i], nttMul(A[i*k+j], s[j])) + } + } + + H := sha3.New256() + ek := dk.EncapsulationKey().Bytes() + H.Write(ek) + H.Sum(dk.h[:0]) +} + +// kemPCT performs a Pairwise Consistency Test per FIPS 140-3 IG 10.3.A +// Additional Comment 1: "For key pairs generated for use with approved KEMs in +// FIPS 203, the PCT shall consist of applying the encapsulation key ek to +// encapsulate a shared secret K leading to ciphertext c, and then applying +// decapsulation key dk to retrieve the same shared secret K. The PCT passes if +// the two shared secret K values are equal. The PCT shall be performed either +// when keys are generated/imported, prior to the first exportation, or prior to +// the first operational use (if not exported before the first use)." +func kemPCT(dk *DecapsulationKey768) error { + ek := dk.EncapsulationKey() + K, c := ek.Encapsulate() + K1, err := dk.Decapsulate(c) + if err != nil { + return err + } + if subtle.ConstantTimeCompare(K, K1) != 1 { + return errors.New("mlkem: PCT failed") + } + return nil +} + +// Encapsulate generates a shared key and an associated ciphertext from an +// encapsulation key, drawing random bytes from a DRBG. +// +// The shared key must be kept secret. +func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { + // The actual logic is in a separate function to outline this allocation. + var cc [CiphertextSize768]byte + return ek.encapsulate(&cc) +} + +func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (sharedKey, ciphertext []byte) { + var m [messageSize]byte + drbg.Read(m[:]) + // Note that the modulus check (step 2 of the encapsulation key check from + // FIPS 203, Section 7.2) is performed by polyByteDecode in parseEK. + fips140.RecordApproved() + return kemEncaps(cc, ek, &m) +} + +// EncapsulateInternal is a derandomized version of Encapsulate, exclusively for +// use in tests. +func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { + cc := &[CiphertextSize768]byte{} + return kemEncaps(cc, ek, m) +} + +// kemEncaps generates a shared key and an associated ciphertext. +// +// It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. +func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (K, c []byte) { + g := sha3.New512() + g.Write(m[:]) + g.Write(ek.h[:]) + G := g.Sum(nil) + K, r := G[:SharedKeySize], G[SharedKeySize:] + c = pkeEncrypt(cc, &ek.encryptionKey, m, r) + return K, c +} + +// NewEncapsulationKey768 parses an encapsulation key from its encoded form. +// If the encapsulation key is not valid, NewEncapsulationKey768 returns an error. +func NewEncapsulationKey768(encapsulationKey []byte) (*EncapsulationKey768, error) { + // The actual logic is in a separate function to outline this allocation. + ek := &EncapsulationKey768{} + return parseEK(ek, encapsulationKey) +} + +// parseEK parses an encryption key from its encoded form. +// +// It implements the initial stages of K-PKE.Encrypt according to FIPS 203, +// Algorithm 14. +func parseEK(ek *EncapsulationKey768, ekPKE []byte) (*EncapsulationKey768, error) { + if len(ekPKE) != EncapsulationKeySize768 { + return nil, errors.New("mlkem: invalid encapsulation key length") + } + + h := sha3.New256() + h.Write(ekPKE) + h.Sum(ek.h[:0]) + + for i := range ek.t { + var err error + ek.t[i], err = polyByteDecode[nttElement](ekPKE[:encodingSize12]) + if err != nil { + return nil, err + } + ekPKE = ekPKE[encodingSize12:] + } + copy(ek.ρ[:], ekPKE) + + for i := byte(0); i < k; i++ { + for j := byte(0); j < k; j++ { + ek.a[i*k+j] = sampleNTT(ek.ρ[:], j, i) + } + } + + return ek, nil +} + +// pkeEncrypt encrypt a plaintext message. +// +// It implements K-PKE.Encrypt according to FIPS 203, Algorithm 14, although the +// computation of t and AT is done in parseEK. +func pkeEncrypt(cc *[CiphertextSize768]byte, ex *encryptionKey, m *[messageSize]byte, rnd []byte) []byte { + var N byte + r, e1 := make([]nttElement, k), make([]ringElement, k) + for i := range r { + r[i] = ntt(samplePolyCBD(rnd, N)) + N++ + } + for i := range e1 { + e1[i] = samplePolyCBD(rnd, N) + N++ + } + e2 := samplePolyCBD(rnd, N) + + u := make([]ringElement, k) // NTT⁻¹(AT ◦ r) + e1 + for i := range u { + u[i] = e1[i] + for j := range r { + // Note that i and j are inverted, as we need the transposed of A. + u[i] = polyAdd(u[i], inverseNTT(nttMul(ex.a[j*k+i], r[j]))) + } + } + + μ := ringDecodeAndDecompress1(m) + + var vNTT nttElement // t⊺ ◦ r + for i := range ex.t { + vNTT = polyAdd(vNTT, nttMul(ex.t[i], r[i])) + } + v := polyAdd(polyAdd(inverseNTT(vNTT), e2), μ) + + c := cc[:0] + for _, f := range u { + c = ringCompressAndEncode10(c, f) + } + c = ringCompressAndEncode4(c, v) + + return c +} + +// Decapsulate generates a shared key from a ciphertext and a decapsulation key. +// If the ciphertext is not valid, Decapsulate returns an error. +// +// The shared key must be kept secret. +func (dk *DecapsulationKey768) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) { + if len(ciphertext) != CiphertextSize768 { + return nil, errors.New("mlkem: invalid ciphertext length") + } + c := (*[CiphertextSize768]byte)(ciphertext) + // Note that the hash check (step 3 of the decapsulation input check from + // FIPS 203, Section 7.3) is foregone as a DecapsulationKey is always + // validly generated by ML-KEM.KeyGen_internal. + return kemDecaps(dk, c), nil +} + +// kemDecaps produces a shared key from a ciphertext. +// +// It implements ML-KEM.Decaps_internal according to FIPS 203, Algorithm 18. +func kemDecaps(dk *DecapsulationKey768, c *[CiphertextSize768]byte) (K []byte) { + fips140.RecordApproved() + m := pkeDecrypt(&dk.decryptionKey, c) + g := sha3.New512() + g.Write(m[:]) + g.Write(dk.h[:]) + G := g.Sum(make([]byte, 0, 64)) + Kprime, r := G[:SharedKeySize], G[SharedKeySize:] + J := sha3.NewShake256() + J.Write(dk.z[:]) + J.Write(c[:]) + Kout := make([]byte, SharedKeySize) + J.Read(Kout) + var cc [CiphertextSize768]byte + c1 := pkeEncrypt(&cc, &dk.encryptionKey, (*[32]byte)(m), r) + + subtle.ConstantTimeCopy(subtle.ConstantTimeCompare(c[:], c1), Kout, Kprime) + return Kout +} + +// pkeDecrypt decrypts a ciphertext. +// +// It implements K-PKE.Decrypt according to FIPS 203, Algorithm 15, +// although s is retained from kemKeyGen. +func pkeDecrypt(dx *decryptionKey, c *[CiphertextSize768]byte) []byte { + u := make([]ringElement, k) + for i := range u { + b := (*[encodingSize10]byte)(c[encodingSize10*i : encodingSize10*(i+1)]) + u[i] = ringDecodeAndDecompress10(b) + } + + b := (*[encodingSize4]byte)(c[encodingSize10*k:]) + v := ringDecodeAndDecompress4(b) + + var mask nttElement // s⊺ ◦ NTT(u) + for i := range dx.s { + mask = polyAdd(mask, nttMul(dx.s[i], ntt(u[i]))) + } + w := polySub(v, inverseNTT(mask)) + + return ringCompressAndEncode1(nil, w) +} diff --git a/crypto/internal/fips140/nistec/_asm/go.mod b/crypto/internal/fips140/nistec/_asm/go.mod new file mode 100644 index 00000000000..09daa240276 --- /dev/null +++ b/crypto/internal/fips140/nistec/_asm/go.mod @@ -0,0 +1,11 @@ +module crypto/internal/fips140/nistec/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/nistec/_asm/go.sum b/crypto/internal/fips140/nistec/_asm/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/nistec/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/internal/nistec/_asm/p256_asm_amd64.go b/crypto/internal/fips140/nistec/_asm/p256_asm.go similarity index 90% rename from crypto/internal/nistec/_asm/p256_asm_amd64.go rename to crypto/internal/fips140/nistec/_asm/p256_asm.go index 4bc73c56c5b..c32e7edf74a 100644 --- a/crypto/internal/nistec/_asm/p256_asm_amd64.go +++ b/crypto/internal/fips140/nistec/_asm/p256_asm.go @@ -21,7 +21,7 @@ import ( . "github.com/mmcloughlin/avo/reg" ) -//go:generate go run . -out ../p256_asm_amd64.s -pkg nistec +//go:generate go run . -out ../p256_asm_amd64.s var ( res_ptr GPPhysical = RDI @@ -43,12 +43,8 @@ var ( ) func main() { - Package("github.com/runZeroInc/excrypto/crypto/internal/nistec") + Package("crypto/internal/fips140/nistec") ConstraintExpr("!purego") - p256OrdLittleToBig() - p256OrdBigToLittle() - p256LittleToBig() - p256BigToLittle() p256MovCond() p256NegCond() p256Sqr() @@ -58,100 +54,24 @@ func main() { p256SelectAffine() p256OrdMul() p256OrdSqr() - p256SubInternalExCrypto() - p256MulInternalExCrypto() - p256SqrInternalExCrypto() + p256SubInternal() + p256MulInternal() + p256SqrInternal() p256PointAddAffineAsm() - p256IsZeroExCrypto() + p256IsZero() p256PointAddAsm() p256PointDoubleAsm() Generate() internalFunctions := []string{ - "·p256SubInternalExCrypto", - "·p256MulInternalExCrypto", - "·p256SqrInternalExCrypto", - "·p256IsZeroExCrypto", + "·p256SubInternal", + "·p256MulInternal", + "·p256SqrInternal", + "·p256IsZero", } removePeskyUnicodeDot(internalFunctions, "../p256_asm_amd64.s") } -// Implements: -// -// func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) -func p256OrdLittleToBig() { - Implement("p256OrdLittleToBig") - Attributes(NOSPLIT) - // Hack to get Avo to output: - // JMP ·p256BigToLittle(SB) - Instruction(&ir.Instruction{ - Opcode: "JMP", - Operands: []Op{ - LabelRef("·p256BigToLittle(SB)"), - }, - }) -} - -// Implements: -// -// func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) -func p256OrdBigToLittle() { - Implement("p256OrdBigToLittle") - Attributes(NOSPLIT) - // Hack to get Avo to output: - // JMP ·p256BigToLittle(SB) - Instruction(&ir.Instruction{ - Opcode: "JMP", - Operands: []Op{ - LabelRef("·p256BigToLittle(SB)"), - }, - }) -} - -// Implements -// -// func p256LittleToBig(res *[32]byte, in *p256Element) -func p256LittleToBig() { - Implement("p256LittleToBig") - Attributes(NOSPLIT) - // Hack to get Avo to output: - // JMP ·p256BigToLittle(SB) - Instruction(&ir.Instruction{ - Opcode: "JMP", - Operands: []Op{ - LabelRef("·p256BigToLittle(SB)"), - }, - }) -} - -// Implements: -// -// func p256BigToLittle(res *p256Element, in *[32]byte) -func p256BigToLittle() { - Implement("p256BigToLittle") - Attributes(NOSPLIT) - - Load(Param("res"), res_ptr) - Load(Param("in"), x_ptr) - - MOVQ(Mem{Base: x_ptr}.Offset(8*0), acc0_v1) - MOVQ(Mem{Base: x_ptr}.Offset(8*1), acc1_v1) - MOVQ(Mem{Base: x_ptr}.Offset(8*2), acc2_v1) - MOVQ(Mem{Base: x_ptr}.Offset(8*3), acc3_v1) - - BSWAPQ(acc0_v1) - BSWAPQ(acc1_v1) - BSWAPQ(acc2_v1) - BSWAPQ(acc3_v1) - - MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*0)) - MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*1)) - MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*2)) - MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*3)) - - RET() -} - // Implements: // // func p256MovCond(res, a, b *P256Point, cond int) @@ -1509,8 +1429,8 @@ var ( hlp_v2 = RBP ) -func p256SubInternalExCrypto() { - Function("p256SubInternalExCrypto") +func p256SubInternal() { + Function("p256SubInternal") Attributes(NOSPLIT) XORQ(mul0_v2, mul0_v2) @@ -1541,8 +1461,8 @@ func p256SubInternalExCrypto() { RET() } -func p256MulInternalExCrypto() { - Function("p256MulInternalExCrypto") +func p256MulInternal() { + Function("p256MulInternal") Attributes(NOSPLIT) MOVQ(acc4_v2, mul0_v2) @@ -1738,8 +1658,8 @@ func p256MulInternalExCrypto() { RET() } -func p256SqrInternalExCrypto() { - Function("p256SqrInternalExCrypto") +func p256SqrInternal() { + Function("p256SqrInternal") Attributes(NOSPLIT) MOVQ(acc4_v2, mul0_v2) @@ -2119,57 +2039,57 @@ func p256PointAddAffineAsm() { Comment("Begin point add") LDacc(z1in_v1) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // z1ˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // z1ˆ2 ST(z1sqr_v1) LDt(x2in_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // x2 * z1ˆ2 + CALL(LabelRef("p256MulInternal(SB)")) // x2 * z1ˆ2 LDt(x1in_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // h = u2 - u1) + CALL(LabelRef("p256SubInternal(SB)")) // h = u2 - u1) ST(h_v1) LDt(z1in_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z3 = h * z1 + CALL(LabelRef("p256MulInternal(SB)")) // z3 = h * z1 ST(zout_v1) LDacc(z1sqr_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z1ˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // z1ˆ3 LDt(y2in_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // s2 = y2 * z1ˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // s2 = y2 * z1ˆ3 ST(s2_v1) LDt(y1in_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // r = s2 - s1) + CALL(LabelRef("p256SubInternal(SB)")) // r = s2 - s1) ST(r_v1) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // rsqr = rˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // rsqr = rˆ2 ST(rsqr_v1) LDacc(h_v1) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // hsqr = hˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // hsqr = hˆ2 ST(hsqr_v1) LDt(h_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // hcub = hˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // hcub = hˆ3 ST(hcub_v1) LDt(y1in_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // y1 * hˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // y1 * hˆ3 ST(s2_v1) LDacc(x1in_v1) LDt(hsqr_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // u1 * hˆ2 + CALL(LabelRef("p256MulInternal(SB)")) // u1 * hˆ2 ST(h_v1) p256MulBy2Inline() // u1 * hˆ2 * 2, inline LDacc(rsqr_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // rˆ2 - u1 * hˆ2 * 2) + CALL(LabelRef("p256SubInternal(SB)")) // rˆ2 - u1 * hˆ2 * 2) LDt(hcub_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) ST(xout_v1) MOVQ(acc4_v2, t0_v2) @@ -2177,13 +2097,13 @@ func p256PointAddAffineAsm() { MOVQ(acc6_v2, t2_v2) MOVQ(acc7_v2, t3_v2) LDacc(h_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) LDt(r_v1) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) LDt(s2_v1) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) ST(yout_v1) Comment("Load stored values from stack") @@ -2299,10 +2219,10 @@ func p256PointAddAffineAsm() { RET() } -// p256IsZeroExCrypto returns 1 in AX if [acc4..acc7] represents zero and zero +// p256IsZero returns 1 in AX if [acc4..acc7] represents zero and zero // otherwise. It writes to [acc4..acc7], t0 and t1. -func p256IsZeroExCrypto() { - Function("p256IsZeroExCrypto") +func p256IsZero() { + Function("p256IsZero") Attributes(NOSPLIT) Comment("AX contains a flag that is set if the input is zero.") @@ -2409,79 +2329,79 @@ func p256PointAddAsm() { Comment("Begin point add") LDacc(z2in_v2) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // z2ˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // z2ˆ2 ST(z2sqr_v2) LDt(z2in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z2ˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // z2ˆ3 LDt(y1in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // s1 = z2ˆ3*y1 + CALL(LabelRef("p256MulInternal(SB)")) // s1 = z2ˆ3*y1 ST(s1_v2) LDacc(z1in_v2) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // z1ˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // z1ˆ2 ST(z1sqr_v2) LDt(z1in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z1ˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // z1ˆ3 LDt(y2in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // s2 = z1ˆ3*y2 + CALL(LabelRef("p256MulInternal(SB)")) // s2 = z1ˆ3*y2 ST(s2_v2) LDt(s1_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // r = s2 - s1 + CALL(LabelRef("p256SubInternal(SB)")) // r = s2 - s1 ST(r_v2) - CALL(LabelRef("p256IsZeroExCrypto(SB)")) + CALL(LabelRef("p256IsZero(SB)")) MOVQ(RAX, points_eq_v2) LDacc(z2sqr_v2) LDt(x1in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // u1 = x1 * z2ˆ2 + CALL(LabelRef("p256MulInternal(SB)")) // u1 = x1 * z2ˆ2 ST(u1_v2) LDacc(z1sqr_v2) LDt(x2in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // u2 = x2 * z1ˆ2 + CALL(LabelRef("p256MulInternal(SB)")) // u2 = x2 * z1ˆ2 ST(u2_v2) LDt(u1_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // h = u2 - u1 + CALL(LabelRef("p256SubInternal(SB)")) // h = u2 - u1 ST(h_v2) - CALL(LabelRef("p256IsZeroExCrypto(SB)")) + CALL(LabelRef("p256IsZero(SB)")) ANDQ(points_eq_v2, RAX) MOVQ(RAX, points_eq_v2) LDacc(r_v2) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // rsqr = rˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // rsqr = rˆ2 ST(rsqr_v2) LDacc(h_v2) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) // hsqr = hˆ2 + CALL(LabelRef("p256SqrInternal(SB)")) // hsqr = hˆ2 ST(hsqr_v2) LDt(h_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // hcub = hˆ3 + CALL(LabelRef("p256MulInternal(SB)")) // hcub = hˆ3 ST(hcub_v2) LDt(s1_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) ST(s2_v2) LDacc(z1in_v2) LDt(z2in_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z1 * z2 + CALL(LabelRef("p256MulInternal(SB)")) // z1 * z2 LDt(h_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // z1 * z2 * h + CALL(LabelRef("p256MulInternal(SB)")) // z1 * z2 * h ST(zout_v2) LDacc(hsqr_v2) LDt(u1_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) // hˆ2 * u1 + CALL(LabelRef("p256MulInternal(SB)")) // hˆ2 * u1 ST(u2_v2) p256MulBy2Inline() // u1 * hˆ2 * 2, inline LDacc(rsqr_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) // rˆ2 - u1 * hˆ2 * 2 + CALL(LabelRef("p256SubInternal(SB)")) // rˆ2 - u1 * hˆ2 * 2 LDt(hcub_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) ST(xout_v2) MOVQ(acc4_v2, t0_v2) @@ -2489,13 +2409,13 @@ func p256PointAddAsm() { MOVQ(acc6_v2, t2_v2) MOVQ(acc7_v2, t3_v2) LDacc(u2_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) LDt(r_v2) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) LDt(s2_v2) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) ST(yout_v2) MOVOU(xout_v2(16*0), X0) @@ -2563,7 +2483,7 @@ func p256PointDoubleAsm() { Comment("Begin point double") LDacc(z) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) + CALL(LabelRef("p256SqrInternal(SB)")) ST(zsqr) LDt(x) @@ -2572,7 +2492,7 @@ func p256PointDoubleAsm() { LDacc(z) LDt(y) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) p256MulBy2Inline() MOVQ(rptr_v3, RAX) @@ -2584,9 +2504,9 @@ func p256PointDoubleAsm() { LDacc(x) LDt(zsqr) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) LDt(m) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) ST(m) Comment("Multiply by 3") @@ -2598,9 +2518,9 @@ func p256PointDoubleAsm() { LDacc(y) p256MulBy2Inline() t2acc() - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) + CALL(LabelRef("p256SqrInternal(SB)")) ST(s) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) + CALL(LabelRef("p256SqrInternal(SB)")) Comment("Divide by 2") XORQ(mul0_v2, mul0_v2) @@ -2632,15 +2552,15 @@ func p256PointDoubleAsm() { Comment("/////////////////////////") LDacc(x) LDt(s) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) ST(s) p256MulBy2Inline() STt(tmp) LDacc(m) - CALL(LabelRef("p256SqrInternalExCrypto(SB)")) + CALL(LabelRef("p256SqrInternal(SB)")) LDt(tmp) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) MOVQ(rptr_v3, RAX) @@ -2652,13 +2572,13 @@ func p256PointDoubleAsm() { acc2t() LDacc(s) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) LDt(m) - CALL(LabelRef("p256MulInternalExCrypto(SB)")) + CALL(LabelRef("p256MulInternal(SB)")) LDt(y) - CALL(LabelRef("p256SubInternalExCrypto(SB)")) + CALL(LabelRef("p256SubInternal(SB)")) MOVQ(rptr_v3, RAX) Comment("Store y") diff --git a/crypto/internal/fips140/nistec/benchmark_test.go b/crypto/internal/fips140/nistec/benchmark_test.go new file mode 100644 index 00000000000..4d5fcff8197 --- /dev/null +++ b/crypto/internal/fips140/nistec/benchmark_test.go @@ -0,0 +1,73 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nistec_test + +import ( + "testing" + + "crypto/rand" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec" +) + +type nistPoint[T any] interface { + Bytes() []byte + SetGenerator() T + SetBytes([]byte) (T, error) + Add(T, T) T + Double(T) T + ScalarMult(T, []byte) (T, error) + ScalarBaseMult([]byte) (T, error) +} + +func BenchmarkScalarMult(b *testing.B) { + b.Run("P224", func(b *testing.B) { + benchmarkScalarMult(b, nistec.NewP224Point().SetGenerator(), 28) + }) + b.Run("P256", func(b *testing.B) { + benchmarkScalarMult(b, nistec.NewP256Point().SetGenerator(), 32) + }) + b.Run("P384", func(b *testing.B) { + benchmarkScalarMult(b, nistec.NewP384Point().SetGenerator(), 48) + }) + b.Run("P521", func(b *testing.B) { + benchmarkScalarMult(b, nistec.NewP521Point().SetGenerator(), 66) + }) +} + +func benchmarkScalarMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) { + scalar := make([]byte, scalarSize) + rand.Read(scalar) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } +} + +func BenchmarkScalarBaseMult(b *testing.B) { + b.Run("P224", func(b *testing.B) { + benchmarkScalarBaseMult(b, nistec.NewP224Point().SetGenerator(), 28) + }) + b.Run("P256", func(b *testing.B) { + benchmarkScalarBaseMult(b, nistec.NewP256Point().SetGenerator(), 32) + }) + b.Run("P384", func(b *testing.B) { + benchmarkScalarBaseMult(b, nistec.NewP384Point().SetGenerator(), 48) + }) + b.Run("P521", func(b *testing.B) { + benchmarkScalarBaseMult(b, nistec.NewP521Point().SetGenerator(), 66) + }) +} + +func benchmarkScalarBaseMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) { + scalar := make([]byte, scalarSize) + rand.Read(scalar) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarBaseMult(scalar) + } +} diff --git a/crypto/internal/nistec/fiat/Dockerfile b/crypto/internal/fips140/nistec/fiat/Dockerfile similarity index 100% rename from crypto/internal/nistec/fiat/Dockerfile rename to crypto/internal/fips140/nistec/fiat/Dockerfile diff --git a/crypto/internal/nistec/fiat/README b/crypto/internal/fips140/nistec/fiat/README similarity index 100% rename from crypto/internal/nistec/fiat/README rename to crypto/internal/fips140/nistec/fiat/README diff --git a/crypto/internal/nistec/fiat/fiat_test.go b/crypto/internal/fips140/nistec/fiat/benchmark_test.go similarity index 94% rename from crypto/internal/nistec/fiat/fiat_test.go rename to crypto/internal/fips140/nistec/fiat/benchmark_test.go index 86d06081105..8033cfa3225 100644 --- a/crypto/internal/nistec/fiat/fiat_test.go +++ b/crypto/internal/fips140/nistec/fiat/benchmark_test.go @@ -5,8 +5,9 @@ package fiat_test import ( - "github.com/runZeroInc/excrypto/crypto/internal/nistec/fiat" "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec/fiat" ) func BenchmarkMul(b *testing.B) { diff --git a/crypto/internal/fips140/nistec/fiat/cast.go b/crypto/internal/fips140/nistec/fiat/cast.go new file mode 100644 index 00000000000..41c00563e06 --- /dev/null +++ b/crypto/internal/fips140/nistec/fiat/cast.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fiat + +import _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" diff --git a/crypto/internal/nistec/fiat/generate.go b/crypto/internal/fips140/nistec/fiat/generate.go similarity index 99% rename from crypto/internal/nistec/fiat/generate.go rename to crypto/internal/fips140/nistec/fiat/generate.go index 0183dc77a88..5e4e013b45d 100644 --- a/crypto/internal/nistec/fiat/generate.go +++ b/crypto/internal/fips140/nistec/fiat/generate.go @@ -152,7 +152,7 @@ const tmplWrapper = `// Copyright 2021 The Go Authors. All rights reserved. package fiat import ( - "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" "errors" ) diff --git a/crypto/internal/nistec/fiat/p224.go b/crypto/internal/fips140/nistec/fiat/p224.go similarity index 94% rename from crypto/internal/nistec/fiat/p224.go rename to crypto/internal/fips140/nistec/fiat/p224.go index 80d793432ad..e066f840666 100644 --- a/crypto/internal/nistec/fiat/p224.go +++ b/crypto/internal/fips140/nistec/fiat/p224.go @@ -7,8 +7,9 @@ package fiat import ( - "github.com/runZeroInc/excrypto/crypto/subtle" "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" ) // P224Element is an integer modulo 2^224 - 2^96 + 1. @@ -78,13 +79,8 @@ func (e *P224Element) SetBytes(v []byte) (*P224Element, error) { // the encoding of -1 mod p, so p - 1, the highest canonical encoding. var minusOneEncoding = new(P224Element).Sub( new(P224Element), new(P224Element).One()).Bytes() - for i := range v { - if v[i] < minusOneEncoding[i] { - break - } - if v[i] > minusOneEncoding[i] { - return nil, errors.New("invalid P224Element encoding") - } + if subtle.ConstantTimeLessOrEqBytes(v, minusOneEncoding) == 0 { + return nil, errors.New("invalid P224Element encoding") } var in [p224ElementLen]byte diff --git a/crypto/internal/nistec/fiat/p224_fiat64.go b/crypto/internal/fips140/nistec/fiat/p224_fiat64.go similarity index 100% rename from crypto/internal/nistec/fiat/p224_fiat64.go rename to crypto/internal/fips140/nistec/fiat/p224_fiat64.go diff --git a/crypto/internal/nistec/fiat/p224_invert.go b/crypto/internal/fips140/nistec/fiat/p224_invert.go similarity index 100% rename from crypto/internal/nistec/fiat/p224_invert.go rename to crypto/internal/fips140/nistec/fiat/p224_invert.go diff --git a/crypto/internal/nistec/fiat/p256.go b/crypto/internal/fips140/nistec/fiat/p256.go similarity index 94% rename from crypto/internal/nistec/fiat/p256.go rename to crypto/internal/fips140/nistec/fiat/p256.go index d01e2d459c6..0c2dd48ab57 100644 --- a/crypto/internal/nistec/fiat/p256.go +++ b/crypto/internal/fips140/nistec/fiat/p256.go @@ -7,8 +7,9 @@ package fiat import ( - "github.com/runZeroInc/excrypto/crypto/subtle" "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" ) // P256Element is an integer modulo 2^256 - 2^224 + 2^192 + 2^96 - 1. @@ -78,13 +79,8 @@ func (e *P256Element) SetBytes(v []byte) (*P256Element, error) { // the encoding of -1 mod p, so p - 1, the highest canonical encoding. var minusOneEncoding = new(P256Element).Sub( new(P256Element), new(P256Element).One()).Bytes() - for i := range v { - if v[i] < minusOneEncoding[i] { - break - } - if v[i] > minusOneEncoding[i] { - return nil, errors.New("invalid P256Element encoding") - } + if subtle.ConstantTimeLessOrEqBytes(v, minusOneEncoding) == 0 { + return nil, errors.New("invalid P256Element encoding") } var in [p256ElementLen]byte diff --git a/crypto/internal/nistec/fiat/p256_fiat64.go b/crypto/internal/fips140/nistec/fiat/p256_fiat64.go similarity index 100% rename from crypto/internal/nistec/fiat/p256_fiat64.go rename to crypto/internal/fips140/nistec/fiat/p256_fiat64.go diff --git a/crypto/internal/nistec/fiat/p256_invert.go b/crypto/internal/fips140/nistec/fiat/p256_invert.go similarity index 100% rename from crypto/internal/nistec/fiat/p256_invert.go rename to crypto/internal/fips140/nistec/fiat/p256_invert.go diff --git a/crypto/internal/nistec/fiat/p384.go b/crypto/internal/fips140/nistec/fiat/p384.go similarity index 94% rename from crypto/internal/nistec/fiat/p384.go rename to crypto/internal/fips140/nistec/fiat/p384.go index fb34d1e1984..0e032b09bb8 100644 --- a/crypto/internal/nistec/fiat/p384.go +++ b/crypto/internal/fips140/nistec/fiat/p384.go @@ -7,8 +7,9 @@ package fiat import ( - "github.com/runZeroInc/excrypto/crypto/subtle" "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" ) // P384Element is an integer modulo 2^384 - 2^128 - 2^96 + 2^32 - 1. @@ -78,13 +79,8 @@ func (e *P384Element) SetBytes(v []byte) (*P384Element, error) { // the encoding of -1 mod p, so p - 1, the highest canonical encoding. var minusOneEncoding = new(P384Element).Sub( new(P384Element), new(P384Element).One()).Bytes() - for i := range v { - if v[i] < minusOneEncoding[i] { - break - } - if v[i] > minusOneEncoding[i] { - return nil, errors.New("invalid P384Element encoding") - } + if subtle.ConstantTimeLessOrEqBytes(v, minusOneEncoding) == 0 { + return nil, errors.New("invalid P384Element encoding") } var in [p384ElementLen]byte diff --git a/crypto/internal/nistec/fiat/p384_fiat64.go b/crypto/internal/fips140/nistec/fiat/p384_fiat64.go similarity index 100% rename from crypto/internal/nistec/fiat/p384_fiat64.go rename to crypto/internal/fips140/nistec/fiat/p384_fiat64.go diff --git a/crypto/internal/nistec/fiat/p384_invert.go b/crypto/internal/fips140/nistec/fiat/p384_invert.go similarity index 100% rename from crypto/internal/nistec/fiat/p384_invert.go rename to crypto/internal/fips140/nistec/fiat/p384_invert.go diff --git a/crypto/internal/nistec/fiat/p521.go b/crypto/internal/fips140/nistec/fiat/p521.go similarity index 94% rename from crypto/internal/nistec/fiat/p521.go rename to crypto/internal/fips140/nistec/fiat/p521.go index 00ebd60c89d..8d59042968d 100644 --- a/crypto/internal/nistec/fiat/p521.go +++ b/crypto/internal/fips140/nistec/fiat/p521.go @@ -7,8 +7,9 @@ package fiat import ( - "github.com/runZeroInc/excrypto/crypto/subtle" "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" ) // P521Element is an integer modulo 2^521 - 1. @@ -78,13 +79,8 @@ func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { // the encoding of -1 mod p, so p - 1, the highest canonical encoding. var minusOneEncoding = new(P521Element).Sub( new(P521Element), new(P521Element).One()).Bytes() - for i := range v { - if v[i] < minusOneEncoding[i] { - break - } - if v[i] > minusOneEncoding[i] { - return nil, errors.New("invalid P521Element encoding") - } + if subtle.ConstantTimeLessOrEqBytes(v, minusOneEncoding) == 0 { + return nil, errors.New("invalid P521Element encoding") } var in [p521ElementLen]byte diff --git a/crypto/internal/nistec/fiat/p521_fiat64.go b/crypto/internal/fips140/nistec/fiat/p521_fiat64.go similarity index 100% rename from crypto/internal/nistec/fiat/p521_fiat64.go rename to crypto/internal/fips140/nistec/fiat/p521_fiat64.go diff --git a/crypto/internal/nistec/fiat/p521_invert.go b/crypto/internal/fips140/nistec/fiat/p521_invert.go similarity index 100% rename from crypto/internal/nistec/fiat/p521_invert.go rename to crypto/internal/fips140/nistec/fiat/p521_invert.go diff --git a/crypto/internal/nistec/generate.go b/crypto/internal/fips140/nistec/generate.go similarity index 97% rename from crypto/internal/nistec/generate.go rename to crypto/internal/fips140/nistec/generate.go index c95dfb461da..a53a2548bb2 100644 --- a/crypto/internal/nistec/generate.go +++ b/crypto/internal/fips140/nistec/generate.go @@ -14,7 +14,6 @@ package main import ( "bytes" "fmt" - "github.com/runZeroInc/excrypto/crypto/elliptic" "go/format" "io" "log" @@ -23,25 +22,20 @@ import ( "os/exec" "strings" "text/template" + + "github.com/runZeroInc/excrypto/crypto/elliptic" ) var curves = []struct { - P string - Element string - Params *elliptic.CurveParams - BuildTags string + P string + Element string + Params *elliptic.CurveParams }{ { P: "P224", Element: "fiat.P224Element", Params: elliptic.P224().Params(), }, - { - P: "P256", - Element: "fiat.P256Element", - Params: elliptic.P256().Params(), - BuildTags: "(!amd64 && !arm64 && !ppc64le && !s390x) || purego", - }, { P: "P384", Element: "fiat.P384Element", @@ -86,7 +80,6 @@ func main() { if err := t.Execute(buf, map[string]interface{}{ "P": c.P, "p": p, "B": B, "Gx": Gx, "Gy": Gy, "Element": c.Element, "ElementLen": elementLen, - "BuildTags": c.BuildTags, }); err != nil { log.Fatal(err) } @@ -145,15 +138,11 @@ const tmplNISTEC = `// Copyright 2022 The Go Authors. All rights reserved. // Code generated by generate.go. DO NOT EDIT. -{{ if .BuildTags }} -//go:build {{ .BuildTags }} -{{ end }} - package nistec import ( - "github.com/runZeroInc/excrypto/crypto/internal/nistec/fiat" - "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec/fiat" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" "errors" "sync" ) diff --git a/crypto/internal/nistec/nistec.go b/crypto/internal/fips140/nistec/nistec.go similarity index 81% rename from crypto/internal/nistec/nistec.go rename to crypto/internal/fips140/nistec/nistec.go index d898d409ca7..e9f74eaddb8 100644 --- a/crypto/internal/nistec/nistec.go +++ b/crypto/internal/fips140/nistec/nistec.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package nistec implements the NIST P elliptic curves from FIPS 186-4. +// Package nistec implements the elliptic curves from NIST SP 800-186. // // This package uses fiat-crypto or specialized assembly and Go code for its // backend field arithmetic (not math/big) and exposes constant-time, heap @@ -12,4 +12,6 @@ // can't be represented. package nistec +import _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + //go:generate go run generate.go diff --git a/crypto/internal/nistec/p224.go b/crypto/internal/fips140/nistec/p224.go similarity index 99% rename from crypto/internal/nistec/p224.go rename to crypto/internal/fips140/nistec/p224.go index f5e22eea2d0..b70402c6912 100644 --- a/crypto/internal/nistec/p224.go +++ b/crypto/internal/fips140/nistec/p224.go @@ -7,8 +7,8 @@ package nistec import ( - "github.com/runZeroInc/excrypto/crypto/internal/nistec/fiat" - "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec/fiat" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" "errors" "sync" ) diff --git a/crypto/internal/nistec/p224_sqrt.go b/crypto/internal/fips140/nistec/p224_sqrt.go similarity index 97% rename from crypto/internal/nistec/p224_sqrt.go rename to crypto/internal/fips140/nistec/p224_sqrt.go index adab127f411..6ec30b1ebcb 100644 --- a/crypto/internal/nistec/p224_sqrt.go +++ b/crypto/internal/fips140/nistec/p224_sqrt.go @@ -5,8 +5,9 @@ package nistec import ( - "github.com/runZeroInc/excrypto/crypto/internal/nistec/fiat" "sync" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec/fiat" ) var p224GG *[96]fiat.P224Element diff --git a/crypto/internal/fips140/nistec/p256.go b/crypto/internal/fips140/nistec/p256.go new file mode 100644 index 00000000000..835b475a16c --- /dev/null +++ b/crypto/internal/fips140/nistec/p256.go @@ -0,0 +1,706 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !arm64 && !ppc64le && !s390x) || purego + +package nistec + +import ( + "errors" + "math/bits" + "sync" + "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/nistec/fiat" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" +) + +// P256Point is a P-256 point. The zero value is NOT valid. +type P256Point struct { + // The point is represented in projective coordinates (X:Y:Z), where x = X/Z + // and y = Y/Z. Infinity is (0:1:0). + // + // fiat.P256Element is a base field element in [0, P-1] in the Montgomery + // domain (with R 2²⁵⁶ and P 2²⁵⁶ - 2²²⁴ + 2¹⁹² + 2⁹⁶ - 1) as four limbs in + // little-endian order value. + x, y, z fiat.P256Element +} + +// NewP256Point returns a new P256Point representing the point at infinity point. +func NewP256Point() *P256Point { + p := &P256Point{} + p.y.One() + return p +} + +// SetGenerator sets p to the canonical generator and returns p. +func (p *P256Point) SetGenerator() *P256Point { + p.x.SetBytes([]byte{0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x3, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}) + p.y.SetBytes([]byte{0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0xf, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}) + p.z.One() + return p +} + +// Set sets p = q and returns p. +func (p *P256Point) Set(q *P256Point) *P256Point { + p.x.Set(&q.x) + p.y.Set(&q.y) + p.z.Set(&q.z) + return p +} + +const p256ElementLength = 32 +const p256UncompressedLength = 1 + 2*p256ElementLength +const p256CompressedLength = 1 + p256ElementLength + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P256Point) SetBytes(b []byte) (*P256Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP256Point()), nil + + // Uncompressed form. + case len(b) == p256UncompressedLength && b[0] == 4: + x, err := new(fiat.P256Element).SetBytes(b[1 : 1+p256ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P256Element).SetBytes(b[1+p256ElementLength:]) + if err != nil { + return nil, err + } + if err := p256CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form. + case len(b) == p256CompressedLength && (b[0] == 2 || b[0] == 3): + x, err := new(fiat.P256Element).SetBytes(b[1:]) + if err != nil { + return nil, err + } + + // y² = x³ - 3x + b + y := p256Polynomial(new(fiat.P256Element), x) + if !p256Sqrt(y, y) { + return nil, errors.New("invalid P256 compressed point encoding") + } + + // Select the positive or negative root, as indicated by the least + // significant bit, based on the encoding type byte. + otherRoot := new(fiat.P256Element) + otherRoot.Sub(otherRoot, y) + cond := y.Bytes()[p256ElementLength-1]&1 ^ b[0]&1 + y.Select(otherRoot, y, int(cond)) + + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + default: + return nil, errors.New("invalid P256 point encoding") + } +} + +var _p256B *fiat.P256Element +var _p256BOnce sync.Once + +func p256B() *fiat.P256Element { + _p256BOnce.Do(func() { + _p256B, _ = new(fiat.P256Element).SetBytes([]byte{0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x6, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}) + }) + return _p256B +} + +// p256Polynomial sets y2 to x³ - 3x + b, and returns y2. +func p256Polynomial(y2, x *fiat.P256Element) *fiat.P256Element { + y2.Square(x) + y2.Mul(y2, x) + + threeX := new(fiat.P256Element).Add(x, x) + threeX.Add(threeX, x) + y2.Sub(y2, threeX) + + return y2.Add(y2, p256B()) +} + +func p256CheckOnCurve(x, y *fiat.P256Element) error { + // y² = x³ - 3x + b + rhs := p256Polynomial(new(fiat.P256Element), x) + lhs := new(fiat.P256Element).Square(y) + if rhs.Equal(lhs) != 1 { + return errors.New("P256 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P256Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p256UncompressedLength]byte + return p.bytes(&out) +} + +func (p *P256Point) bytes(out *[p256UncompressedLength]byte) []byte { + // The SEC 1 representation of the point at infinity is a single zero byte, + // and only infinity has z = 0. + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P256Element).Invert(&p.z) + x := new(fiat.P256Element).Mul(&p.x, zinv) + y := new(fiat.P256Element).Mul(&p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, x.Bytes()...) + buf = append(buf, y.Bytes()...) + return buf +} + +// BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1, +// Version 2.0, Section 2.3.5, or an error if p is the point at infinity. +func (p *P256Point) BytesX() ([]byte, error) { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p256ElementLength]byte + return p.bytesX(&out) +} + +func (p *P256Point) bytesX(out *[p256ElementLength]byte) ([]byte, error) { + if p.z.IsZero() == 1 { + return nil, errors.New("P256 point is the point at infinity") + } + + zinv := new(fiat.P256Element).Invert(&p.z) + x := new(fiat.P256Element).Mul(&p.x, zinv) + + return append(out[:0], x.Bytes()...), nil +} + +// BytesCompressed returns the compressed or infinity encoding of p, as +// specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the +// point at infinity is shorter than all other encodings. +func (p *P256Point) BytesCompressed() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p256CompressedLength]byte + return p.bytesCompressed(&out) +} + +func (p *P256Point) bytesCompressed(out *[p256CompressedLength]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P256Element).Invert(&p.z) + x := new(fiat.P256Element).Mul(&p.x, zinv) + y := new(fiat.P256Element).Mul(&p.y, zinv) + + // Encode the sign of the y coordinate (indicated by the least significant + // bit) as the encoding type (2 or 3). + buf := append(out[:0], 2) + buf[0] |= y.Bytes()[p256ElementLength-1] & 1 + buf = append(buf, x.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P256Point) Add(p1, p2 *P256Point) *P256Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P256Element).Mul(&p1.x, &p2.x) // t0 := X1 * X2 + t1 := new(fiat.P256Element).Mul(&p1.y, &p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P256Element).Mul(&p1.z, &p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P256Element).Add(&p1.x, &p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P256Element).Add(&p2.x, &p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(&p1.y, &p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P256Element).Add(&p2.y, &p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(&p1.x, &p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P256Element).Add(&p2.x, &p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P256Element).Mul(p256B(), t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p256B(), y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P256Point) Double(p *P256Point) *P256Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P256Element).Square(&p.x) // t0 := X ^ 2 + t1 := new(fiat.P256Element).Square(&p.y) // t1 := Y ^ 2 + t2 := new(fiat.P256Element).Square(&p.z) // t2 := Z ^ 2 + t3 := new(fiat.P256Element).Mul(&p.x, &p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P256Element).Mul(&p.x, &p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P256Element).Mul(p256B(), t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P256Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p256B(), z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(&p.y, &p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// p256AffinePoint is a point in affine coordinates (x, y). x and y are still +// Montgomery domain elements. The point can't be the point at infinity. +type p256AffinePoint struct { + x, y fiat.P256Element +} + +func (p *p256AffinePoint) Projective() *P256Point { + pp := &P256Point{x: p.x, y: p.y} + pp.z.One() + return pp +} + +// AddAffine sets q = p1 + p2, if infinity == 0, and to p1 if infinity == 1. +// p2 can't be the point at infinity as it can't be represented in affine +// coordinates, instead callers can set p2 to an arbitrary point and set +// infinity to 1. +func (q *P256Point) AddAffine(p1 *P256Point, p2 *p256AffinePoint, infinity int) *P256Point { + // Complete mixed addition formula for a = -3 from "Complete addition + // formulas for prime order elliptic curves" + // (https://eprint.iacr.org/2015/1060), Algorithm 5. + + t0 := new(fiat.P256Element).Mul(&p1.x, &p2.x) // t0 ← X1 · X2 + t1 := new(fiat.P256Element).Mul(&p1.y, &p2.y) // t1 ← Y1 · Y2 + t3 := new(fiat.P256Element).Add(&p2.x, &p2.y) // t3 ← X2 + Y2 + t4 := new(fiat.P256Element).Add(&p1.x, &p1.y) // t4 ← X1 + Y1 + t3.Mul(t3, t4) // t3 ← t3 · t4 + t4.Add(t0, t1) // t4 ← t0 + t1 + t3.Sub(t3, t4) // t3 ← t3 − t4 + t4.Mul(&p2.y, &p1.z) // t4 ← Y2 · Z1 + t4.Add(t4, &p1.y) // t4 ← t4 + Y1 + y3 := new(fiat.P256Element).Mul(&p2.x, &p1.z) // Y3 ← X2 · Z1 + y3.Add(y3, &p1.x) // Y3 ← Y3 + X1 + z3 := new(fiat.P256Element).Mul(p256B(), &p1.z) // Z3 ← b · Z1 + x3 := new(fiat.P256Element).Sub(y3, z3) // X3 ← Y3 − Z3 + z3.Add(x3, x3) // Z3 ← X3 + X3 + x3.Add(x3, z3) // X3 ← X3 + Z3 + z3.Sub(t1, x3) // Z3 ← t1 − X3 + x3.Add(t1, x3) // X3 ← t1 + X3 + y3.Mul(p256B(), y3) // Y3 ← b · Y3 + t1.Add(&p1.z, &p1.z) // t1 ← Z1 + Z1 + t2 := new(fiat.P256Element).Add(t1, &p1.z) // t2 ← t1 + Z1 + y3.Sub(y3, t2) // Y3 ← Y3 − t2 + y3.Sub(y3, t0) // Y3 ← Y3 − t0 + t1.Add(y3, y3) // t1 ← Y3 + Y3 + y3.Add(t1, y3) // Y3 ← t1 + Y3 + t1.Add(t0, t0) // t1 ← t0 + t0 + t0.Add(t1, t0) // t0 ← t1 + t0 + t0.Sub(t0, t2) // t0 ← t0 − t2 + t1.Mul(t4, y3) // t1 ← t4 · Y3 + t2.Mul(t0, y3) // t2 ← t0 · Y3 + y3.Mul(x3, z3) // Y3 ← X3 · Z3 + y3.Add(y3, t2) // Y3 ← Y3 + t2 + x3.Mul(t3, x3) // X3 ← t3 · X3 + x3.Sub(x3, t1) // X3 ← X3 − t1 + z3.Mul(t4, z3) // Z3 ← t4 · Z3 + t1.Mul(t3, t0) // t1 ← t3 · t0 + z3.Add(z3, t1) // Z3 ← Z3 + t1 + + q.x.Select(&p1.x, x3, infinity) + q.y.Select(&p1.y, y3, infinity) + q.z.Select(&p1.z, z3, infinity) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P256Point) Select(p1, p2 *P256Point, cond int) *P256Point { + q.x.Select(&p1.x, &p2.x, cond) + q.y.Select(&p1.y, &p2.y, cond) + q.z.Select(&p1.z, &p2.z, cond) + return q +} + +// p256OrdElement is a P-256 scalar field element in [0, ord(G)-1] in the +// Montgomery domain (with R 2²⁵⁶) as four uint64 limbs in little-endian order. +type p256OrdElement [4]uint64 + +// SetBytes sets s to the big-endian value of x, reducing it as necessary. +func (s *p256OrdElement) SetBytes(x []byte) (*p256OrdElement, error) { + if len(x) != 32 { + return nil, errors.New("invalid scalar length") + } + + s[0] = byteorder.BEUint64(x[24:]) + s[1] = byteorder.BEUint64(x[16:]) + s[2] = byteorder.BEUint64(x[8:]) + s[3] = byteorder.BEUint64(x[:]) + + // Ensure s is in the range [0, ord(G)-1]. Since 2 * ord(G) > 2²⁵⁶, we can + // just conditionally subtract ord(G), keeping the result if it doesn't + // underflow. + t0, b := bits.Sub64(s[0], 0xf3b9cac2fc632551, 0) + t1, b := bits.Sub64(s[1], 0xbce6faada7179e84, b) + t2, b := bits.Sub64(s[2], 0xffffffffffffffff, b) + t3, b := bits.Sub64(s[3], 0xffffffff00000000, b) + tMask := b - 1 // zero if subtraction underflowed + s[0] ^= (t0 ^ s[0]) & tMask + s[1] ^= (t1 ^ s[1]) & tMask + s[2] ^= (t2 ^ s[2]) & tMask + s[3] ^= (t3 ^ s[3]) & tMask + + return s, nil +} + +func (s *p256OrdElement) Bytes() []byte { + var out [32]byte + byteorder.BEPutUint64(out[24:], s[0]) + byteorder.BEPutUint64(out[16:], s[1]) + byteorder.BEPutUint64(out[8:], s[2]) + byteorder.BEPutUint64(out[:], s[3]) + return out[:] +} + +// Rsh returns the 64 least significant bits of x >> n. n must be lower +// than 256. The value of n leaks through timing side-channels. +func (s *p256OrdElement) Rsh(n int) uint64 { + i := n / 64 + n = n % 64 + res := s[i] >> n + // Shift in the more significant limb, if present. + if i := i + 1; i < len(s) { + res |= s[i] << (64 - n) + } + return res +} + +// p256Table is a table of the first 16 multiples of a point. Points are stored +// at an index offset of -1 so [8]P is at index 7, P is at 0, and [16]P is at 15. +// [0]P is the point at infinity and it's not stored. +type p256Table [16]P256Point + +// Select selects the n-th multiple of the table base point into p. It works in +// constant time. n must be in [0, 16]. If n is 0, p is set to the identity point. +func (table *p256Table) Select(p *P256Point, n uint8) { + if n > 16 { + panic("nistec: internal error: p256Table called with out-of-bounds value") + } + p.Set(NewP256Point()) + for i := uint8(1); i <= 16; i++ { + cond := subtle.ConstantTimeByteEq(i, n) + p.Select(&table[i-1], p, cond) + } +} + +// Compute populates the table to the first 16 multiples of q. +func (table *p256Table) Compute(q *P256Point) *p256Table { + table[0].Set(q) + for i := 1; i < 16; i += 2 { + table[i].Double(&table[i/2]) + if i+1 < 16 { + table[i+1].Add(&table[i], q) + } + } + return table +} + +func boothW5(in uint64) (uint8, int) { + s := ^((in >> 5) - 1) + d := (1 << 6) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return uint8(d), int(s & 1) +} + +// ScalarMult sets r = scalar * q, where scalar is a 32-byte big endian value, +// and returns r. If scalar is not 32 bytes long, ScalarMult returns an error +// and the receiver is unchanged. +func (p *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) { + s, err := new(p256OrdElement).SetBytes(scalar) + if err != nil { + return nil, err + } + + // Start scanning the window from the most significant bits. We move by + // 5 bits at a time and need to finish at -1, so -1 + 5 * 51 = 254. + index := 254 + + sel, sign := boothW5(s.Rsh(index)) + // sign is always zero because the boothW5 input here is at + // most two bits long, so the top bit is never set. + _ = sign + + // Neither Select nor Add have exceptions for the point at infinity / + // selector zero, so we don't need to check for it here or in the loop. + table := new(p256Table).Compute(q) + table.Select(p, sel) + + t := NewP256Point() + for index >= 4 { + index -= 5 + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + if index >= 0 { + sel, sign = boothW5(s.Rsh(index) & 0b111111) + } else { + // Booth encoding considers a virtual zero bit at index -1, + // so we shift left the least significant limb. + wvalue := (s[0] << 1) & 0b111111 + sel, sign = boothW5(wvalue) + } + + table.Select(t, sel) + t.Negate(sign) + p.Add(p, t) + } + + return p, nil +} + +// Negate sets p to -p, if cond == 1, and to p if cond == 0. +func (p *P256Point) Negate(cond int) *P256Point { + negY := new(fiat.P256Element) + negY.Sub(negY, &p.y) + p.y.Select(negY, &p.y, cond) + return p +} + +// p256AffineTable is a table of the first 32 multiples of a point. Points are +// stored at an index offset of -1 like in p256Table, and [0]P is not stored. +type p256AffineTable [32]p256AffinePoint + +// Select selects the n-th multiple of the table base point into p. It works in +// constant time. n can be in [0, 32], but (unlike p256Table.Select) if n is 0, +// p is set to an undefined value. +func (table *p256AffineTable) Select(p *p256AffinePoint, n uint8) { + if n > 32 { + panic("nistec: internal error: p256AffineTable.Select called with out-of-bounds value") + } + for i := uint8(1); i <= 32; i++ { + cond := subtle.ConstantTimeByteEq(i, n) + p.x.Select(&table[i-1].x, &p.x, cond) + p.y.Select(&table[i-1].y, &p.y, cond) + } +} + +// p256GeneratorTables is a series of precomputed multiples of G, the canonical +// generator. The first p256AffineTable contains multiples of G. The second one +// multiples of [2⁶]G, the third one of [2¹²]G, and so on, where each successive +// table is the previous table doubled six times. Six is the width of the +// sliding window used in ScalarBaseMult, and having each table already +// pre-doubled lets us avoid the doublings between windows entirely. This table +// aliases into p256PrecomputedEmbed. +var p256GeneratorTables *[43]p256AffineTable + +func init() { + p256GeneratorTablesPtr := unsafe.Pointer(&p256PrecomputedEmbed) + if cpu.BigEndian { + var newTable [43 * 32 * 2 * 4]uint64 + for i, x := range (*[43 * 32 * 2 * 4][8]byte)(p256GeneratorTablesPtr) { + newTable[i] = byteorder.LEUint64(x[:]) + } + p256GeneratorTablesPtr = unsafe.Pointer(&newTable) + } + p256GeneratorTables = (*[43]p256AffineTable)(p256GeneratorTablesPtr) +} + +func boothW6(in uint64) (uint8, int) { + s := ^((in >> 6) - 1) + d := (1 << 7) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return uint8(d), int(s & 1) +} + +// ScalarBaseMult sets p = scalar * generator, where scalar is a 32-byte big +// endian value, and returns r. If scalar is not 32 bytes long, ScalarBaseMult +// returns an error and the receiver is unchanged. +func (p *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) { + // This function works like ScalarMult above, but the table is fixed and + // "pre-doubled" for each iteration, so instead of doubling we move to the + // next table at each iteration. + + s, err := new(p256OrdElement).SetBytes(scalar) + if err != nil { + return nil, err + } + + // Start scanning the window from the most significant bits. We move by + // 6 bits at a time and need to finish at -1, so -1 + 6 * 42 = 251. + index := 251 + + sel, sign := boothW6(s.Rsh(index)) + // sign is always zero because the boothW6 input here is at + // most five bits long, so the top bit is never set. + _ = sign + + t := &p256AffinePoint{} + table := &p256GeneratorTables[(index+1)/6] + table.Select(t, sel) + + // Select's output is undefined if the selector is zero, when it should be + // the point at infinity (because infinity can't be represented in affine + // coordinates). Here we conditionally set p to the infinity if sel is zero. + // In the loop, that's handled by AddAffine. + selIsZero := subtle.ConstantTimeByteEq(sel, 0) + p.Select(NewP256Point(), t.Projective(), selIsZero) + + for index >= 5 { + index -= 6 + + if index >= 0 { + sel, sign = boothW6(s.Rsh(index) & 0b1111111) + } else { + // Booth encoding considers a virtual zero bit at index -1, + // so we shift left the least significant limb. + wvalue := (s[0] << 1) & 0b1111111 + sel, sign = boothW6(wvalue) + } + + table := &p256GeneratorTables[(index+1)/6] + table.Select(t, sel) + t.Negate(sign) + selIsZero := subtle.ConstantTimeByteEq(sel, 0) + p.AddAffine(p, t, selIsZero) + } + + return p, nil +} + +// Negate sets p to -p, if cond == 1, and to p if cond == 0. +func (p *p256AffinePoint) Negate(cond int) *p256AffinePoint { + negY := new(fiat.P256Element) + negY.Sub(negY, &p.y) + p.y.Select(negY, &p.y, cond) + return p +} + +// p256Sqrt sets e to a square root of x. If x is not a square, p256Sqrt returns +// false and e is unchanged. e and x can overlap. +func p256Sqrt(e, x *fiat.P256Element) (isSquare bool) { + t0, t1 := new(fiat.P256Element), new(fiat.P256Element) + + // Since p = 3 mod 4, exponentiation by (p + 1) / 4 yields a square root candidate. + // + // The sequence of 7 multiplications and 253 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.4.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _1100 = _11 << 2 + // _1111 = _11 + _1100 + // _11110000 = _1111 << 4 + // _11111111 = _1111 + _11110000 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // return ((x32 << 32 + 1) << 96 + 1) << 94 + // + p256Square(t0, x, 1) + t0.Mul(x, t0) + p256Square(t1, t0, 2) + t0.Mul(t0, t1) + p256Square(t1, t0, 4) + t0.Mul(t0, t1) + p256Square(t1, t0, 8) + t0.Mul(t0, t1) + p256Square(t1, t0, 16) + t0.Mul(t0, t1) + p256Square(t0, t0, 32) + t0.Mul(x, t0) + p256Square(t0, t0, 96) + t0.Mul(x, t0) + p256Square(t0, t0, 94) + + // Check if the candidate t0 is indeed a square root of x. + t1.Square(t0) + if t1.Equal(x) != 1 { + return false + } + e.Set(t0) + return true +} + +// p256Square sets e to the square of x, repeated n times > 1. +func p256Square(e, x *fiat.P256Element, n int) { + e.Square(x) + for i := 1; i < n; i++ { + e.Square(e) + } +} diff --git a/crypto/internal/nistec/p256_asm.go b/crypto/internal/fips140/nistec/p256_asm.go similarity index 94% rename from crypto/internal/nistec/p256_asm.go rename to crypto/internal/fips140/nistec/p256_asm.go index 7f6c03d3224..6e79082a550 100644 --- a/crypto/internal/nistec/p256_asm.go +++ b/crypto/internal/fips140/nistec/p256_asm.go @@ -15,12 +15,12 @@ package nistec import ( - _ "embed" "errors" - "github.com/runZeroInc/excrypto/internal/byteorder" "math/bits" "runtime" "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" ) // p256Element is a P-256 base field element in [0, P-1] in the Montgomery @@ -178,6 +178,28 @@ func p256LessThanP(x *p256Element) int { return int(b) } +func p256BigToLittle(l *p256Element, b *[32]byte) { + bytesToLimbs((*[4]uint64)(l), b) +} + +func bytesToLimbs(l *[4]uint64, b *[32]byte) { + l[0] = byteorder.BEUint64(b[24:]) + l[1] = byteorder.BEUint64(b[16:]) + l[2] = byteorder.BEUint64(b[8:]) + l[3] = byteorder.BEUint64(b[:]) +} + +func p256LittleToBig(b *[32]byte, l *p256Element) { + limbsToBytes(b, (*[4]uint64)(l)) +} + +func limbsToBytes(b *[32]byte, l *[4]uint64) { + byteorder.BEPutUint64(b[24:], l[0]) + byteorder.BEPutUint64(b[16:], l[1]) + byteorder.BEPutUint64(b[8:], l[2]) + byteorder.BEPutUint64(b[:], l[3]) +} + // p256Add sets res = x + y. func p256Add(res, x, y *p256Element) { var c, b uint64 @@ -277,18 +299,6 @@ func p256NegCond(val *p256Element, cond int) //go:noescape func p256MovCond(res, a, b *P256Point, cond int) -//go:noescape -func p256BigToLittle(res *p256Element, in *[32]byte) - -//go:noescape -func p256LittleToBig(res *[32]byte, in *p256Element) - -//go:noescape -func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) - -//go:noescape -func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) - // p256Table is a table of the first 16 multiples of a point. Points are stored // at an index offset of -1 so [8]P is at index 7, P is at 0, and [16]P is at 15. // [0]P is the point at infinity and it's not stored. @@ -314,25 +324,21 @@ type p256AffineTable [32]p256AffinePoint // generator. The first p256AffineTable contains multiples of G. The second one // multiples of [2⁶]G, the third one of [2¹²]G, and so on, where each successive // table is the previous table doubled six times. Six is the width of the -// sliding window used in p256ScalarMult, and having each table already +// sliding window used in p256ScalarBaseMult, and having each table already // pre-doubled lets us avoid the doublings between windows entirely. This table -// MUST NOT be modified, as it aliases into p256PrecomputedEmbed below. +// aliases into p256PrecomputedEmbed. var p256Precomputed *[43]p256AffineTable -//go:embed p256_asm_table.bin -var p256PrecomputedEmbed string - func init() { - p256PrecomputedPtr := (*unsafe.Pointer)(unsafe.Pointer(&p256PrecomputedEmbed)) + p256PrecomputedPtr := unsafe.Pointer(&p256PrecomputedEmbed) if runtime.GOARCH == "s390x" { var newTable [43 * 32 * 2 * 4]uint64 - for i, x := range (*[43 * 32 * 2 * 4][8]byte)(*p256PrecomputedPtr) { - newTable[i] = byteorder.LeUint64(x[:]) + for i, x := range (*[43 * 32 * 2 * 4][8]byte)(p256PrecomputedPtr) { + newTable[i] = byteorder.LEUint64(x[:]) } - newTablePtr := unsafe.Pointer(&newTable) - p256PrecomputedPtr = &newTablePtr + p256PrecomputedPtr = unsafe.Pointer(&newTable) } - p256Precomputed = (*[43]p256AffineTable)(*p256PrecomputedPtr) + p256Precomputed = (*[43]p256AffineTable)(p256PrecomputedPtr) } // p256SelectAffine sets res to the point at index idx in the table. @@ -379,6 +385,14 @@ func p256OrdReduce(s *p256OrdElement) { s[3] ^= (t3 ^ s[3]) & tMask } +func p256OrdLittleToBig(b *[32]byte, l *p256OrdElement) { + limbsToBytes(b, (*[4]uint64)(l)) +} + +func p256OrdBigToLittle(l *p256OrdElement, b *[32]byte) { + bytesToLimbs((*[4]uint64)(l), b) +} + // Add sets q = p1 + p2, and returns q. The points may overlap. func (q *P256Point) Add(r1, r2 *P256Point) *P256Point { var sum, double P256Point diff --git a/crypto/internal/nistec/p256_asm_amd64.s b/crypto/internal/fips140/nistec/p256_asm_amd64.s similarity index 93% rename from crypto/internal/nistec/p256_asm_amd64.s rename to crypto/internal/fips140/nistec/p256_asm_amd64.s index 06676bbc785..64894891e98 100644 --- a/crypto/internal/nistec/p256_asm_amd64.s +++ b/crypto/internal/fips140/nistec/p256_asm_amd64.s @@ -1,39 +1,9 @@ -// Code generated by command: go run p256_asm_amd64.go -out ../p256_asm_amd64.s -pkg nistec. DO NOT EDIT. +// Code generated by command: go run p256_asm.go -out ../p256_asm_amd64.s. DO NOT EDIT. //go:build !purego #include "textflag.h" -// func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) -TEXT ·p256OrdLittleToBig(SB), NOSPLIT, $0-16 - JMP ·p256BigToLittle(SB) - -// func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) -TEXT ·p256OrdBigToLittle(SB), NOSPLIT, $0-16 - JMP ·p256BigToLittle(SB) - -// func p256LittleToBig(res *[32]byte, in *p256Element) -TEXT ·p256LittleToBig(SB), NOSPLIT, $0-16 - JMP ·p256BigToLittle(SB) - -// func p256BigToLittle(res *p256Element, in *[32]byte) -TEXT ·p256BigToLittle(SB), NOSPLIT, $0-16 - MOVQ res+0(FP), DI - MOVQ in+8(FP), SI - MOVQ (SI), R8 - MOVQ 8(SI), R9 - MOVQ 16(SI), R10 - MOVQ 24(SI), R11 - BSWAPQ R8 - BSWAPQ R9 - BSWAPQ R10 - BSWAPQ R11 - MOVQ R11, (DI) - MOVQ R10, 8(DI) - MOVQ R9, 16(DI) - MOVQ R8, 24(DI) - RET - // func p256MovCond(res *P256Point, a *P256Point, b *P256Point, cond int) // Requires: SSE2 TEXT ·p256MovCond(SB), NOSPLIT, $0-32 @@ -1173,9 +1143,9 @@ ordSqrLoop: JNE ordSqrLoop RET -// func p256SubInternalExCrypto() +// func p256SubInternal() // Requires: CMOV -TEXT p256SubInternalExCrypto(SB), NOSPLIT, $0 +TEXT p256SubInternal(SB), NOSPLIT, $0 XORQ AX, AX SUBQ R14, R10 SBBQ R15, R11 @@ -1197,9 +1167,9 @@ TEXT p256SubInternalExCrypto(SB), NOSPLIT, $0 CMOVQEQ R9, R13 RET -// func p256MulInternalExCrypto() +// func p256MulInternal() // Requires: CMOV -TEXT p256MulInternalExCrypto(SB), NOSPLIT, $8 +TEXT p256MulInternal(SB), NOSPLIT, $8 MOVQ R10, AX MULQ R14 MOVQ AX, BX @@ -1374,9 +1344,9 @@ TEXT p256MulInternalExCrypto(SB), NOSPLIT, $8 CMOVQCS R9, R13 RET -// func p256SqrInternalExCrypto() +// func p256SqrInternal() // Requires: CMOV -TEXT p256SqrInternalExCrypto(SB), NOSPLIT, $8 +TEXT p256SqrInternal(SB), NOSPLIT, $8 MOVQ R10, AX MULQ R11 MOVQ AX, CX @@ -1600,7 +1570,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 72(SP), R11 MOVQ 80(SP), R12 MOVQ 88(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 288(SP) MOVQ R11, 296(SP) MOVQ R12, 304(SP) @@ -1609,12 +1579,12 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 104(SP), R15 MOVQ 112(SP), DI MOVQ 120(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ (SP), R14 MOVQ 8(SP), R15 MOVQ 16(SP), DI MOVQ 24(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 320(SP) MOVQ R11, 328(SP) MOVQ R12, 336(SP) @@ -1623,7 +1593,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 72(SP), R15 MOVQ 80(SP), DI MOVQ 88(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 224(SP) MOVQ R11, 232(SP) MOVQ R12, 240(SP) @@ -1632,12 +1602,12 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 296(SP), R11 MOVQ 304(SP), R12 MOVQ 312(SP), R13 - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 128(SP), R14 MOVQ 136(SP), R15 MOVQ 144(SP), DI MOVQ 152(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 256(SP) MOVQ R11, 264(SP) MOVQ R12, 272(SP) @@ -1646,12 +1616,12 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 40(SP), R15 MOVQ 48(SP), DI MOVQ 56(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 352(SP) MOVQ R11, 360(SP) MOVQ R12, 368(SP) MOVQ R13, 376(SP) - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 416(SP) MOVQ R11, 424(SP) MOVQ R12, 432(SP) @@ -1660,7 +1630,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 328(SP), R11 MOVQ 336(SP), R12 MOVQ 344(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 384(SP) MOVQ R11, 392(SP) MOVQ R12, 400(SP) @@ -1669,7 +1639,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 328(SP), R15 MOVQ 336(SP), DI MOVQ 344(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 448(SP) MOVQ R11, 456(SP) MOVQ R12, 464(SP) @@ -1678,7 +1648,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 40(SP), R15 MOVQ 48(SP), DI MOVQ 56(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 256(SP) MOVQ R11, 264(SP) MOVQ R12, 272(SP) @@ -1691,7 +1661,7 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 392(SP), R15 MOVQ 400(SP), DI MOVQ 408(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 320(SP) MOVQ R11, 328(SP) MOVQ R12, 336(SP) @@ -1719,12 +1689,12 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 424(SP), R11 MOVQ 432(SP), R12 MOVQ 440(SP), R13 - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 448(SP), R14 MOVQ 456(SP), R15 MOVQ 464(SP), DI MOVQ 472(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 160(SP) MOVQ R11, 168(SP) MOVQ R12, 176(SP) @@ -1737,17 +1707,17 @@ TEXT ·p256PointAddAffineAsm(SB), $512-48 MOVQ 328(SP), R11 MOVQ 336(SP), R12 MOVQ 344(SP), R13 - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 352(SP), R14 MOVQ 360(SP), R15 MOVQ 368(SP), DI MOVQ 376(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 256(SP), R14 MOVQ 264(SP), R15 MOVQ 272(SP), DI MOVQ 280(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 192(SP) MOVQ R11, 200(SP) MOVQ R12, 208(SP) @@ -1845,9 +1815,9 @@ DATA p256one<>+16(SB)/8, $0xffffffffffffffff DATA p256one<>+24(SB)/8, $0x00000000fffffffe GLOBL p256one<>(SB), RODATA, $32 -// func p256IsZeroExCrypto() +// func p256IsZero() // Requires: CMOV -TEXT p256IsZeroExCrypto(SB), NOSPLIT, $0 +TEXT p256IsZero(SB), NOSPLIT, $0 // AX contains a flag that is set if the input is zero. XORQ AX, AX MOVQ $0x00000001, R15 @@ -1914,7 +1884,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 168(SP), R11 MOVQ 176(SP), R12 MOVQ 184(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 448(SP) MOVQ R11, 456(SP) MOVQ R12, 464(SP) @@ -1923,12 +1893,12 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 168(SP), R15 MOVQ 176(SP), DI MOVQ 184(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 32(SP), R14 MOVQ 40(SP), R15 MOVQ 48(SP), DI MOVQ 56(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 352(SP) MOVQ R11, 360(SP) MOVQ R12, 368(SP) @@ -1937,7 +1907,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 72(SP), R11 MOVQ 80(SP), R12 MOVQ 88(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 416(SP) MOVQ R11, 424(SP) MOVQ R12, 432(SP) @@ -1946,12 +1916,12 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 72(SP), R15 MOVQ 80(SP), DI MOVQ 88(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 128(SP), R14 MOVQ 136(SP), R15 MOVQ 144(SP), DI MOVQ 152(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 384(SP) MOVQ R11, 392(SP) MOVQ R12, 400(SP) @@ -1960,12 +1930,12 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 360(SP), R15 MOVQ 368(SP), DI MOVQ 376(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 512(SP) MOVQ R11, 520(SP) MOVQ R12, 528(SP) MOVQ R13, 536(SP) - CALL p256IsZeroExCrypto(SB) + CALL p256IsZero(SB) MOVQ AX, 648(SP) MOVQ 448(SP), R10 MOVQ 456(SP), R11 @@ -1975,7 +1945,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 8(SP), R15 MOVQ 16(SP), DI MOVQ 24(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 288(SP) MOVQ R11, 296(SP) MOVQ R12, 304(SP) @@ -1988,7 +1958,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 104(SP), R15 MOVQ 112(SP), DI MOVQ 120(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 320(SP) MOVQ R11, 328(SP) MOVQ R12, 336(SP) @@ -1997,19 +1967,19 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 296(SP), R15 MOVQ 304(SP), DI MOVQ 312(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 480(SP) MOVQ R11, 488(SP) MOVQ R12, 496(SP) MOVQ R13, 504(SP) - CALL p256IsZeroExCrypto(SB) + CALL p256IsZero(SB) ANDQ 648(SP), AX MOVQ AX, 648(SP) MOVQ 512(SP), R10 MOVQ 520(SP), R11 MOVQ 528(SP), R12 MOVQ 536(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 576(SP) MOVQ R11, 584(SP) MOVQ R12, 592(SP) @@ -2018,7 +1988,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 488(SP), R11 MOVQ 496(SP), R12 MOVQ 504(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 544(SP) MOVQ R11, 552(SP) MOVQ R12, 560(SP) @@ -2027,7 +1997,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 488(SP), R15 MOVQ 496(SP), DI MOVQ 504(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 608(SP) MOVQ R11, 616(SP) MOVQ R12, 624(SP) @@ -2036,7 +2006,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 360(SP), R15 MOVQ 368(SP), DI MOVQ 376(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 384(SP) MOVQ R11, 392(SP) MOVQ R12, 400(SP) @@ -2049,12 +2019,12 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 168(SP), R15 MOVQ 176(SP), DI MOVQ 184(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 480(SP), R14 MOVQ 488(SP), R15 MOVQ 496(SP), DI MOVQ 504(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 256(SP) MOVQ R11, 264(SP) MOVQ R12, 272(SP) @@ -2067,7 +2037,7 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 296(SP), R15 MOVQ 304(SP), DI MOVQ 312(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 320(SP) MOVQ R11, 328(SP) MOVQ R12, 336(SP) @@ -2095,12 +2065,12 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 584(SP), R11 MOVQ 592(SP), R12 MOVQ 600(SP), R13 - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 608(SP), R14 MOVQ 616(SP), R15 MOVQ 624(SP), DI MOVQ 632(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 192(SP) MOVQ R11, 200(SP) MOVQ R12, 208(SP) @@ -2113,17 +2083,17 @@ TEXT ·p256PointAddAsm(SB), $680-32 MOVQ 328(SP), R11 MOVQ 336(SP), R12 MOVQ 344(SP), R13 - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 512(SP), R14 MOVQ 520(SP), R15 MOVQ 528(SP), DI MOVQ 536(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 384(SP), R14 MOVQ 392(SP), R15 MOVQ 400(SP), DI MOVQ 408(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ R10, 224(SP) MOVQ R11, 232(SP) MOVQ R12, 240(SP) @@ -2174,7 +2144,7 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 72(SP), R11 MOVQ 80(SP), R12 MOVQ 88(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 160(SP) MOVQ R11, 168(SP) MOVQ R12, 176(SP) @@ -2214,7 +2184,7 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 40(SP), R15 MOVQ 48(SP), DI MOVQ 56(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) XORQ AX, AX ADDQ R10, R10 ADCQ R11, R11 @@ -2249,12 +2219,12 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 168(SP), R15 MOVQ 176(SP), DI MOVQ 184(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 128(SP), R14 MOVQ 136(SP), R15 MOVQ 144(SP), DI MOVQ 152(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 128(SP) MOVQ R11, 136(SP) MOVQ R12, 144(SP) @@ -2336,12 +2306,12 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ R15, R11 MOVQ DI, R12 MOVQ SI, R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ R10, 96(SP) MOVQ R11, 104(SP) MOVQ R12, 112(SP) MOVQ R13, 120(SP) - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) // Divide by 2 XORQ AX, AX @@ -2378,7 +2348,7 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 104(SP), R15 MOVQ 112(SP), DI MOVQ 120(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ R10, 96(SP) MOVQ R11, 104(SP) MOVQ R12, 112(SP) @@ -2410,12 +2380,12 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 136(SP), R11 MOVQ 144(SP), R12 MOVQ 152(SP), R13 - CALL p256SqrInternalExCrypto(SB) + CALL p256SqrInternal(SB) MOVQ 192(SP), R14 MOVQ 200(SP), R15 MOVQ 208(SP), DI MOVQ 216(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 224(SP), AX // Store x @@ -2431,17 +2401,17 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $256-16 MOVQ 104(SP), R11 MOVQ 112(SP), R12 MOVQ 120(SP), R13 - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 128(SP), R14 MOVQ 136(SP), R15 MOVQ 144(SP), DI MOVQ 152(SP), SI - CALL p256MulInternalExCrypto(SB) + CALL p256MulInternal(SB) MOVQ 32(SP), R14 MOVQ 40(SP), R15 MOVQ 48(SP), DI MOVQ 56(SP), SI - CALL p256SubInternalExCrypto(SB) + CALL p256SubInternal(SB) MOVQ 224(SP), AX // Store y diff --git a/crypto/internal/nistec/p256_asm_arm64.s b/crypto/internal/fips140/nistec/p256_asm_arm64.s similarity index 88% rename from crypto/internal/nistec/p256_asm_arm64.s rename to crypto/internal/fips140/nistec/p256_asm_arm64.s index e7c8689d07a..33da24508e2 100644 --- a/crypto/internal/nistec/p256_asm_arm64.s +++ b/crypto/internal/fips140/nistec/p256_asm_arm64.s @@ -65,35 +65,6 @@ GLOBL p256ordK0<>(SB), 8, $8 GLOBL p256ord<>(SB), 8, $32 GLOBL p256one<>(SB), 8, $32 -/* ---------------------------------------*/ -// func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) -TEXT ·p256OrdLittleToBig(SB),NOSPLIT,$0 - JMP ·p256BigToLittle(SB) -/* ---------------------------------------*/ -// func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) -TEXT ·p256OrdBigToLittle(SB),NOSPLIT,$0 - JMP ·p256BigToLittle(SB) -/* ---------------------------------------*/ -// func p256LittleToBig(res *[32]byte, in *p256Element) -TEXT ·p256LittleToBig(SB),NOSPLIT,$0 - JMP ·p256BigToLittle(SB) -/* ---------------------------------------*/ -// func p256BigToLittle(res *p256Element, in *[32]byte) -TEXT ·p256BigToLittle(SB),NOSPLIT,$0 - MOVD res+0(FP), res_ptr - MOVD in+8(FP), a_ptr - - LDP 0*16(a_ptr), (acc0, acc1) - LDP 1*16(a_ptr), (acc2, acc3) - - REV acc0, acc0 - REV acc1, acc1 - REV acc2, acc2 - REV acc3, acc3 - - STP (acc3, acc2), 0*16(res_ptr) - STP (acc1, acc0), 1*16(res_ptr) - RET /* ---------------------------------------*/ // func p256MovCond(res, a, b *P256Point, cond int) // If cond == 0 res=b, else res=a @@ -185,7 +156,7 @@ TEXT ·p256Sqr(SB),NOSPLIT,$0 sqrLoop: SUB $1, b_ptr - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) MOVD y0, x0 MOVD y1, x1 MOVD y2, x2 @@ -211,7 +182,7 @@ TEXT ·p256Mul(SB),NOSPLIT,$0 LDP 0*16(b_ptr), (y0, y1) LDP 1*16(b_ptr), (y2, y3) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) STP (y0, y1), 0*16(res_ptr) STP (y2, y3), 1*16(res_ptr) @@ -791,7 +762,7 @@ TEXT ·p256OrdMul(SB),NOSPLIT,$0 RET /* ---------------------------------------*/ -TEXT p256SubInternalExCrypto<>(SB),NOSPLIT,$0 +TEXT p256SubInternal<>(SB),NOSPLIT,$0 SUBS x0, y0, acc0 SBCS x1, y1, acc1 SBCS x2, y2, acc2 @@ -811,7 +782,7 @@ TEXT p256SubInternalExCrypto<>(SB),NOSPLIT,$0 RET /* ---------------------------------------*/ -TEXT p256SqrInternalExCrypto<>(SB),NOSPLIT,$0 +TEXT p256SqrInternal<>(SB),NOSPLIT,$0 // x[1:] * x[0] MUL x0, x1, acc1 UMULH x0, x1, acc2 @@ -920,7 +891,7 @@ TEXT p256SqrInternalExCrypto<>(SB),NOSPLIT,$0 CSEL CS, t3, acc3, y3 RET /* ---------------------------------------*/ -TEXT p256MulInternalExCrypto<>(SB),NOSPLIT,$0 +TEXT p256MulInternal<>(SB),NOSPLIT,$0 // y[0] * x MUL y0, x0, acc0 UMULH y0, x0, acc1 @@ -1147,18 +1118,18 @@ TEXT ·p256PointAddAffineAsm(SB),0,$264-48 STy(y2in) // Begin point add LDx(z1in) - CALL p256SqrInternalExCrypto<>(SB) // z1ˆ2 + CALL p256SqrInternal<>(SB) // z1ˆ2 STy(z1sqr) LDx(x2in) - CALL p256MulInternalExCrypto<>(SB) // x2 * z1ˆ2 + CALL p256MulInternal<>(SB) // x2 * z1ˆ2 LDx(x1in) - CALL p256SubInternalExCrypto<>(SB) // h = u2 - u1 + CALL p256SubInternal<>(SB) // h = u2 - u1 STx(h) LDy(z1in) - CALL p256MulInternalExCrypto<>(SB) // z3 = h * z1 + CALL p256MulInternal<>(SB) // z3 = h * z1 LDP 4*16(a_ptr), (acc0, acc1)// iff select[0] == 0, z3 = z1 LDP 5*16(a_ptr), (acc2, acc3) @@ -1180,49 +1151,49 @@ TEXT ·p256PointAddAffineAsm(SB),0,$264-48 STP (y2, y3), 5*16(t0) LDy(z1sqr) - CALL p256MulInternalExCrypto<>(SB) // z1 ^ 3 + CALL p256MulInternal<>(SB) // z1 ^ 3 LDx(y2in) - CALL p256MulInternalExCrypto<>(SB) // s2 = y2 * z1ˆ3 + CALL p256MulInternal<>(SB) // s2 = y2 * z1ˆ3 STy(s2) LDx(y1in) - CALL p256SubInternalExCrypto<>(SB) // r = s2 - s1 + CALL p256SubInternal<>(SB) // r = s2 - s1 STx(r) - CALL p256SqrInternalExCrypto<>(SB) // rsqr = rˆ2 + CALL p256SqrInternal<>(SB) // rsqr = rˆ2 STy (rsqr) LDx(h) - CALL p256SqrInternalExCrypto<>(SB) // hsqr = hˆ2 + CALL p256SqrInternal<>(SB) // hsqr = hˆ2 STy(hsqr) - CALL p256MulInternalExCrypto<>(SB) // hcub = hˆ3 + CALL p256MulInternal<>(SB) // hcub = hˆ3 STy(hcub) LDx(y1in) - CALL p256MulInternalExCrypto<>(SB) // y1 * hˆ3 + CALL p256MulInternal<>(SB) // y1 * hˆ3 STy(s2) LDP hsqr(0*8), (x0, x1) LDP hsqr(2*8), (x2, x3) LDP 0*16(a_ptr), (y0, y1) LDP 1*16(a_ptr), (y2, y3) - CALL p256MulInternalExCrypto<>(SB) // u1 * hˆ2 + CALL p256MulInternal<>(SB) // u1 * hˆ2 STP (y0, y1), h(0*8) STP (y2, y3), h(2*8) p256MulBy2Inline // u1 * hˆ2 * 2, inline LDy(rsqr) - CALL p256SubInternalExCrypto<>(SB) // rˆ2 - u1 * hˆ2 * 2 + CALL p256SubInternal<>(SB) // rˆ2 - u1 * hˆ2 * 2 MOVD x0, y0 MOVD x1, y1 MOVD x2, y2 MOVD x3, y3 LDx(hcub) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDP 0*16(a_ptr), (acc0, acc1) LDP 1*16(a_ptr), (acc2, acc3) @@ -1244,15 +1215,15 @@ TEXT ·p256PointAddAffineAsm(SB),0,$264-48 LDP h(0*8), (y0, y1) LDP h(2*8), (y2, y3) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDP r(0*8), (y0, y1) LDP r(2*8), (y2, y3) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) LDP s2(0*8), (x0, x1) LDP s2(2*8), (x2, x3) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDP 2*16(a_ptr), (acc0, acc1) LDP 3*16(a_ptr), (acc2, acc3) ANDS $1, hlp1, ZR // iff select[0] == 0, y3 = y1 @@ -1305,7 +1276,7 @@ TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16 // Begin point double LDP 4*16(a_ptr), (x0, x1) LDP 5*16(a_ptr), (x2, x3) - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) STP (y0, y1), zsqr(0*8) STP (y2, y3), zsqr(2*8) @@ -1316,15 +1287,15 @@ TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16 LDx(z1in) LDy(y1in) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) p256MulBy2Inline STx(z3out) LDy(x1in) LDx(zsqr) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDy(m) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // Multiply by 3 p256MulBy2Inline @@ -1333,13 +1304,13 @@ TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16 LDy(y1in) p256MulBy2Inline - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) STy(s) MOVD y0, x0 MOVD y1, x1 MOVD y2, x2 MOVD y3, x3 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // Divide by 2 ADDS $-1, y0, t0 @@ -1363,26 +1334,26 @@ TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16 LDx(x1in) LDy(s) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) STy(s) p256MulBy2Inline STx(tmp) LDx(m) - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) LDx(tmp) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) STx(x3out) LDy(s) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDy(m) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) LDx(y3out) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) STx(y3out) RET /* ---------------------------------------*/ @@ -1406,26 +1377,26 @@ TEXT ·p256PointAddAsm(SB),0,$392-32 // Begin point add LDx(z2in) - CALL p256SqrInternalExCrypto<>(SB) // z2^2 + CALL p256SqrInternal<>(SB) // z2^2 STy(z2sqr) - CALL p256MulInternalExCrypto<>(SB) // z2^3 + CALL p256MulInternal<>(SB) // z2^3 LDx(y1in) - CALL p256MulInternalExCrypto<>(SB) // s1 = z2ˆ3*y1 + CALL p256MulInternal<>(SB) // s1 = z2ˆ3*y1 STy(s1) LDx(z1in) - CALL p256SqrInternalExCrypto<>(SB) // z1^2 + CALL p256SqrInternal<>(SB) // z1^2 STy(z1sqr) - CALL p256MulInternalExCrypto<>(SB) // z1^3 + CALL p256MulInternal<>(SB) // z1^3 LDx(y2in) - CALL p256MulInternalExCrypto<>(SB) // s2 = z1ˆ3*y2 + CALL p256MulInternal<>(SB) // s2 = z1ˆ3*y2 LDx(s1) - CALL p256SubInternalExCrypto<>(SB) // r = s2 - s1 + CALL p256SubInternal<>(SB) // r = s2 - s1 STx(r) MOVD $1, t2 @@ -1447,16 +1418,16 @@ TEXT ·p256PointAddAsm(SB),0,$392-32 LDx(z2sqr) LDy(x1in) - CALL p256MulInternalExCrypto<>(SB) // u1 = x1 * z2ˆ2 + CALL p256MulInternal<>(SB) // u1 = x1 * z2ˆ2 STy(u1) LDx(z1sqr) LDy(x2in) - CALL p256MulInternalExCrypto<>(SB) // u2 = x2 * z1ˆ2 + CALL p256MulInternal<>(SB) // u2 = x2 * z1ˆ2 STy(u2) LDx(u1) - CALL p256SubInternalExCrypto<>(SB) // h = u2 - u1 + CALL p256SubInternal<>(SB) // h = u2 - u1 STx(h) MOVD $1, t2 @@ -1479,54 +1450,54 @@ TEXT ·p256PointAddAsm(SB),0,$392-32 AND hlp0, hlp1, hlp1 LDx(r) - CALL p256SqrInternalExCrypto<>(SB) // rsqr = rˆ2 + CALL p256SqrInternal<>(SB) // rsqr = rˆ2 STy(rsqr) LDx(h) - CALL p256SqrInternalExCrypto<>(SB) // hsqr = hˆ2 + CALL p256SqrInternal<>(SB) // hsqr = hˆ2 STy(hsqr) LDx(h) - CALL p256MulInternalExCrypto<>(SB) // hcub = hˆ3 + CALL p256MulInternal<>(SB) // hcub = hˆ3 STy(hcub) LDx(s1) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) STy(s2) LDx(z1in) LDy(z2in) - CALL p256MulInternalExCrypto<>(SB) // z1 * z2 + CALL p256MulInternal<>(SB) // z1 * z2 LDx(h) - CALL p256MulInternalExCrypto<>(SB) // z1 * z2 * h + CALL p256MulInternal<>(SB) // z1 * z2 * h MOVD res+0(FP), b_ptr STy(z3out) LDx(hsqr) LDy(u1) - CALL p256MulInternalExCrypto<>(SB) // hˆ2 * u1 + CALL p256MulInternal<>(SB) // hˆ2 * u1 STy(u2) p256MulBy2Inline // u1 * hˆ2 * 2, inline LDy(rsqr) - CALL p256SubInternalExCrypto<>(SB) // rˆ2 - u1 * hˆ2 * 2 + CALL p256SubInternal<>(SB) // rˆ2 - u1 * hˆ2 * 2 MOVD x0, y0 MOVD x1, y1 MOVD x2, y2 MOVD x3, y3 LDx(hcub) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) STx(x3out) LDy(u2) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) LDy(r) - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) LDx(s2) - CALL p256SubInternalExCrypto<>(SB) + CALL p256SubInternal<>(SB) STx(y3out) MOVD hlp1, R0 diff --git a/crypto/internal/nistec/p256_asm_ppc64le.s b/crypto/internal/fips140/nistec/p256_asm_ppc64le.s similarity index 94% rename from crypto/internal/nistec/p256_asm_ppc64le.s rename to crypto/internal/fips140/nistec/p256_asm_ppc64le.s index d1120031140..7efaa6ac187 100644 --- a/crypto/internal/nistec/p256_asm_ppc64le.s +++ b/crypto/internal/fips140/nistec/p256_asm_ppc64le.s @@ -126,14 +126,23 @@ GLOBL p256mul<>(SB), 8, $160 #define PH V31 #define CAR1 V6 + +#define SEL V8 +#define ZER V9 + // func p256NegCond(val *p256Point, cond int) TEXT ·p256NegCond(SB), NOSPLIT, $0-16 MOVD val+0(FP), P1ptr MOVD $16, R16 - MOVD cond+8(FP), R6 - CMP $0, R6 - BC 12, 2, LR // just return if cond == 0 + // Copy cond into SEL (cond is R1 + 8 (cond offset) + 32) + MOVD $40, R17 + LXVDSX (R1)(R17), SEL + // Zeroize ZER + VSPLTISB $0, ZER + // SEL controls whether to return the original value (Y1H/Y1L) + // or the negated value (T1H/T1L). + VCMPEQUD SEL, ZER, SEL MOVD $p256mul<>+0x00(SB), CPOOL @@ -150,6 +159,9 @@ TEXT ·p256NegCond(SB), NOSPLIT, $0-16 VSUBUQM PL, Y1L, T1L // subtract part2 giving result VSUBEUQM PH, Y1H, CAR1, T1H // subtract part1 using carry from part2 + VSEL T1H, Y1H, SEL, T1H + VSEL T1L, Y1L, SEL, T1L + XXPERMDI T1H, T1H, $2, T1H XXPERMDI T1L, T1L, $2, T1L @@ -166,6 +178,8 @@ TEXT ·p256NegCond(SB), NOSPLIT, $0-16 #undef PL #undef PH #undef CAR1 +#undef SEL +#undef ZER #define P3ptr R3 #define P1ptr R4 @@ -291,7 +305,7 @@ TEXT ·p256Select(SB), NOSPLIT, $0-24 VSPLTB $7, SEL1, IDX // splat byte VSPLTISB $1, ONE // VREPIB $1, ONE VSPLTISB $1, SEL2 // VREPIB $1, SEL2 - MOVD $17, COUNT + MOVD $16, COUNT // len(p256Table) MOVD COUNT, CTR // set up ctr VSPLTISB $0, X1H // VZERO X1H @@ -362,50 +376,6 @@ loop_select: #undef SEL1 #undef SEL2 -// The following functions all reverse the byte order. - -//func p256BigToLittle(res *p256Element, in *[32]byte) -TEXT ·p256BigToLittle(SB), NOSPLIT, $0-16 - MOVD res+0(FP), R3 - MOVD in+8(FP), R4 - BR p256InternalEndianSwap<>(SB) - -//func p256LittleToBig(res *[32]byte, in *p256Element) -TEXT ·p256LittleToBig(SB), NOSPLIT, $0-16 - MOVD res+0(FP), R3 - MOVD in+8(FP), R4 - BR p256InternalEndianSwap<>(SB) - -//func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) -TEXT ·p256OrdBigToLittle(SB), NOSPLIT, $0-16 - MOVD res+0(FP), R3 - MOVD in+8(FP), R4 - BR p256InternalEndianSwap<>(SB) - -//func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) -TEXT ·p256OrdLittleToBig(SB), NOSPLIT, $0-16 - MOVD res+0(FP), R3 - MOVD in+8(FP), R4 - BR p256InternalEndianSwap<>(SB) - -TEXT p256InternalEndianSwap<>(SB), NOSPLIT, $0-0 - // Index registers needed for BR movs - MOVD $8, R9 - MOVD $16, R10 - MOVD $24, R14 - - MOVDBR (R0)(R4), R5 - MOVDBR (R9)(R4), R6 - MOVDBR (R10)(R4), R7 - MOVDBR (R14)(R4), R8 - - MOVD R8, 0(R3) - MOVD R7, 8(R3) - MOVD R6, 16(R3) - MOVD R5, 24(R3) - - RET - #define P3ptr R3 #define P1ptr R4 #define COUNT R5 @@ -441,7 +411,7 @@ TEXT ·p256SelectAffine(SB), NOSPLIT, $0-24 VSPLTISB $1, ONE // Vector with byte 1s VSPLTISB $1, SEL2 // Vector with byte 1s - MOVD $64, COUNT + MOVD $32, COUNT // len(p256AffineTable) MOVD COUNT, CTR // loop count VSPLTISB $0, X1H // VZERO X1H @@ -637,7 +607,7 @@ TEXT ·p256FromMont(SB), NOSPLIT, $0-16 #undef PH // --------------------------------------- -// p256MulInternalExCrypto +// p256MulInternal // V0-V3 V30,V31 - Not Modified // V4-V15 V27-V29 - Volatile @@ -786,7 +756,7 @@ TEXT ·p256FromMont(SB), NOSPLIT, $0-16 * * Last 'group' needs to RED2||RED1 shifted less */ -TEXT p256MulInternalExCrypto<>(SB), NOSPLIT, $0-16 +TEXT p256MulInternal<>(SB), NOSPLIT, $0-16 // CPOOL loaded from caller MOVD $16, R16 MOVD $32, R17 @@ -1065,7 +1035,7 @@ TEXT p256MulInternalExCrypto<>(SB), NOSPLIT, $0-16 #undef TMP1 #undef TMP2 -#define p256SubInternalExCrypto(T1, T0, X1, X0, Y1, Y0) \ +#define p256SubInternal(T1, T0, X1, X0, Y1, Y0) \ VSPLTISB $0, ZER \ // VZERO VSUBCUQ X0, Y0, CAR1 \ VSUBUQM X0, Y0, T0 \ @@ -1164,7 +1134,7 @@ TEXT ·p256Mul(SB), NOSPLIT, $0-24 LXVD2X (R16)(CPOOL), P1 LXVD2X (R0)(CPOOL), P0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) MOVD $p256mul<>+0x00(SB), CPOOL @@ -1198,7 +1168,7 @@ sqrLoop: LXVD2X (R16)(CPOOL), P1 LXVD2X (R0)(CPOOL), P0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) MOVD n+16(FP), N ADD $-1, N @@ -1331,7 +1301,7 @@ SUB(T(SB) + CALL p256MulInternal<>(SB) // X=T ; Y- ; MUL; T2=T // T2 = T1*Z1 T1 T2 VOR T0, T0, X0 VOR T1, T1, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T2L VOR T1, T1, T2H @@ -1400,7 +1370,7 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 LXVD2X (R16)(P2ptr), Y1 // X2L XXPERMDI Y0, Y0, $2, Y0 XXPERMDI Y1, Y1, $2, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T1L VOR T1, T1, T1H @@ -1409,7 +1379,7 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 VOR T2H, T2H, X1 VOR Y2L, Y2L, Y0 VOR Y2H, Y2H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T2(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, Z3L VOR T1, T1, Z3H @@ -1439,12 +1409,12 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 // X=Y; Y- ; MUL; X=T // T3 = T1*T1 T2 VOR Y0, Y0, X0 VOR Y1, Y1, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, X0 VOR T1, T1, X1 // X- ; Y- ; MUL; T4=T // T4 = T3*T1 T2 T4 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T4L VOR T1, T1, T4H @@ -1454,7 +1424,7 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 LXVD2X (R16)(P1ptr), Y1 // X1L XXPERMDI Y1, Y1, $2, Y1 XXPERMDI Y0, Y0, $2, Y0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T3L VOR T1, T1, T3H @@ -1466,21 +1436,21 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 VOR T2H, T2H, X1 VOR T2L, T2L, Y0 VOR T2H, T2H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T3L VOR T1, T1, T3H @@ -1492,10 +1462,10 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $16-48 LXVD2X (R18)(P1ptr), Y1 // Y1L XXPERMDI Y0, Y0, $2, Y0 XXPERMDI Y1, Y1, $2, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T(SB) + CALL p256MulInternal<>(SB) // SUB(X(SB) + CALL p256MulInternal<>(SB) // ADD(T2(SB) + CALL p256MulInternal<>(SB) // Leave T0, T1 as is. XXPERMDI T0, T0, $2, TT0 @@ -1767,7 +1737,7 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $0-16 // X- ; Y=X ; MUL; T- // Y3 = Y3² VOR X0, X0, Y0 VOR X1, X1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // X=T ; Y=X1; MUL; T3=T // T3 = Y3*X1 VOR T0, T0, X0 @@ -1776,14 +1746,14 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $0-16 LXVD2X (R16)(P1ptr), Y1 XXPERMDI Y0, Y0, $2, Y0 XXPERMDI Y1, Y1, $2, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T3L VOR T1, T1, T3H // X- ; Y=X ; MUL; T- // Y3 = Y3² VOR X0, X0, Y0 VOR X1, X1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // HAL(Y3(SB) + CALL p256MulInternal<>(SB) // ADD(T1(SB) + CALL p256MulInternal<>(SB) // SUB(Y3(SB) + CALL p256MulInternal<>(SB) // X- ; Y=T ; MUL; R=T // R = Z1*T1 VOR T0, T0, Y0 VOR T1, T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, RL // SAVE: RL VOR T1, T1, RH // SAVE: RH @@ -2003,7 +1973,7 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 LXVD2X (R16)(P2ptr), X1 // X2H XXPERMDI X0, X0, $2, X0 XXPERMDI X1, X1, $2, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, HL // SAVE: HL VOR T1, T1, HH // SAVE: HH @@ -2015,12 +1985,12 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 XXPERMDI X1, X1, $2, X1 VOR X0, X0, Y0 VOR X1, X1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // X- ; Y=T ; MUL; S1=T // S1 = Z2*T2 VOR T0, T0, Y0 VOR T1, T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, S1L // SAVE: S1L VOR T1, T1, S1H // SAVE: S1H @@ -2030,12 +2000,12 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 LXVD2X (R16)(P1ptr), X1 // X1H XXPERMDI X0, X0, $2, X0 XXPERMDI X1, X1, $2, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, U1L // SAVE: U1L VOR T1, T1, U1H // SAVE: U1H // SUB(H(SB) + CALL p256MulInternal<>(SB) // X=T ; Y=H ; MUL; Z3:=T// Z3 = Z3*H VOR T0, T0, X0 VOR T1, T1, X1 VOR HL, HL, Y0 VOR HH, HH, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) MOVD res+0(FP), P3ptr XXPERMDI T1, T1, $2, TT1 XXPERMDI T0, T0, $2, TT0 @@ -2089,7 +2059,7 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 XXPERMDI X1, X1, $2, X1 VOR S1L, S1L, Y0 VOR S1H, S1H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, S1L VOR T1, T1, S1H @@ -2103,10 +2073,10 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 // VOR RH, RH, Y1 RH was saved above in D2X format LXVD2X (R1)(R17), Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(R(SB) + CALL p256MulInternal<>(SB) // X- ; Y=T ; MUL; T2=T // T2 = H*T1 VOR T0, T0, Y0 VOR T1, T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, T2L VOR T1, T1, T2H // X=U1; Y- ; MUL; U1=T // U1 = U1*T1 VOR U1L, U1L, X0 VOR U1H, U1H, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, U1L VOR T1, T1, U1H @@ -2164,16 +2134,16 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 VOR X1, X1, Y1 // VOR RH, RH, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T(SB) + CALL p256MulInternal<>(SB) VOR T0, T0, U1L VOR T1, T1, U1H @@ -2197,10 +2167,10 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $16-32 VOR S1H, S1H, X1 VOR T2L, T2L, Y0 VOR T2H, T2H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T+0x00(SB)/4, $0xee00bc4f -DATA p256ord<>+0x00(SB)/8, $0xffffffff00000000 -DATA p256ord<>+0x08(SB)/8, $0xffffffffffffffff -DATA p256ord<>+0x10(SB)/8, $0xbce6faada7179e84 -DATA p256ord<>+0x18(SB)/8, $0xf3b9cac2fc632551 DATA p256<>+0x00(SB)/8, $0xffffffff00000001 // P256 DATA p256<>+0x08(SB)/8, $0x0000000000000000 // P256 DATA p256<>+0x10(SB)/8, $0x00000000ffffffff // P256 @@ -44,49 +39,9 @@ DATA p256mul<>+0x80(SB)/8, $0x00000000fffffffe // (1*2^256)%P256 DATA p256mul<>+0x88(SB)/8, $0xffffffffffffffff // (1*2^256)%P256 DATA p256mul<>+0x90(SB)/8, $0xffffffff00000000 // (1*2^256)%P256 DATA p256mul<>+0x98(SB)/8, $0x0000000000000001 // (1*2^256)%P256 -GLOBL p256ordK0<>(SB), 8, $4 -GLOBL p256ord<>(SB), 8, $32 GLOBL p256<>(SB), 8, $96 GLOBL p256mul<>(SB), 8, $160 -// func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement) -TEXT ·p256OrdLittleToBig(SB), NOSPLIT, $0 - JMP ·p256BigToLittle(SB) - -// func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte) -TEXT ·p256OrdBigToLittle(SB), NOSPLIT, $0 - JMP ·p256BigToLittle(SB) - -// --------------------------------------- -// func p256LittleToBig(res *[32]byte, in *p256Element) -TEXT ·p256LittleToBig(SB), NOSPLIT, $0 - JMP ·p256BigToLittle(SB) - -// func p256BigToLittle(res *p256Element, in *[32]byte) -#define res_ptr R1 -#define in_ptr R2 -#define T1L V2 -#define T1H V3 - -TEXT ·p256BigToLittle(SB), NOSPLIT, $0 - MOVD res+0(FP), res_ptr - MOVD in+8(FP), in_ptr - - VL 0(in_ptr), T1H - VL 16(in_ptr), T1L - - VPDI $0x4, T1L, T1L, T1L - VPDI $0x4, T1H, T1H, T1H - - VST T1L, 0(res_ptr) - VST T1H, 16(res_ptr) - RET - -#undef res_ptr -#undef in_ptr -#undef T1L -#undef T1H - // --------------------------------------- // iff cond == 1 val <- -val // func p256NegCond(val *p256Element, cond int) @@ -508,7 +463,7 @@ loop_select: VAB SEL2, ONE, SEL2 ADDW $1, COUNT ADD $64, P1ptr - CMPW COUNT, $65 + CMPW COUNT, $33 // len(p256AffineTable) + 1 BLT loop_select VST X1H, 0(P3ptr) VST X1L, 16(P3ptr) @@ -539,393 +494,7 @@ loop_select: #undef CPOOL // --------------------------------------- - -// func p256OrdMul(res, in1, in2 *p256OrdElement) -#define res_ptr R1 -#define x_ptr R2 -#define y_ptr R3 -#define X0 V0 -#define X1 V1 -#define Y0 V2 -#define Y1 V3 -#define M0 V4 -#define M1 V5 -#define T0 V6 -#define T1 V7 -#define T2 V8 -#define YDIG V9 - -#define ADD1 V16 -#define ADD1H V17 -#define ADD2 V18 -#define ADD2H V19 -#define RED1 V20 -#define RED1H V21 -#define RED2 V22 -#define RED2H V23 -#define CAR1 V24 -#define CAR1M V25 - -#define MK0 V30 -#define K0 V31 -TEXT ·p256OrdMul<>(SB), NOSPLIT, $0 - MOVD res+0(FP), res_ptr - MOVD in1+8(FP), x_ptr - MOVD in2+16(FP), y_ptr - - VZERO T2 - MOVD $p256ordK0<>+0x00(SB), R4 - - // VLEF $3, 0(R4), K0 - WORD $0xE7F40000 - BYTE $0x38 - BYTE $0x03 - MOVD $p256ord<>+0x00(SB), R4 - VL 16(R4), M0 - VL 0(R4), M1 - - VL (0*16)(x_ptr), X0 - VPDI $0x4, X0, X0, X0 - VL (1*16)(x_ptr), X1 - VPDI $0x4, X1, X1, X1 - VL (0*16)(y_ptr), Y0 - VPDI $0x4, Y0, Y0, Y0 - VL (1*16)(y_ptr), Y1 - VPDI $0x4, Y1, Y1, Y1 - - // ---------------------------------------------------------------------------/ - VREPF $3, Y0, YDIG - VMLF X0, YDIG, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMLF X1, YDIG, ADD2 - VMLHF X0, YDIG, ADD1H - VMLHF X1, YDIG, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- -/* * - * ---+--------+--------+ - * T2| T1 | T0 | - * ---+--------+--------+ - * *(add)* - * +--------+--------+ - * | X1 | X0 | - * +--------+--------+ - * *(mul)* - * +--------+--------+ - * | YDIG | YDIG | - * +--------+--------+ - * *(add)* - * +--------+--------+ - * | M1 | M0 | - * +--------+--------+ - * *(mul)* - * +--------+--------+ - * | MK0 | MK0 | - * +--------+--------+ - * - * --------------------- - * - * +--------+--------+ - * | ADD2 | ADD1 | - * +--------+--------+ - * +--------+--------+ - * | ADD2H | ADD1H | - * +--------+--------+ - * +--------+--------+ - * | RED2 | RED1 | - * +--------+--------+ - * +--------+--------+ - * | RED2H | RED1H | - * +--------+--------+ - */ - VREPF $2, Y0, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $1, Y0, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $0, Y0, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $3, Y1, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $2, Y1, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $1, Y1, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - VREPF $0, Y1, YDIG - VMALF X0, YDIG, T0, ADD1 - VMLF ADD1, K0, MK0 - VREPF $3, MK0, MK0 - - VMALF X1, YDIG, T1, ADD2 - VMALHF X0, YDIG, T0, ADD1H - VMALHF X1, YDIG, T1, ADD2H - - VMALF M0, MK0, ADD1, RED1 - VMALHF M0, MK0, ADD1, RED1H - VMALF M1, MK0, ADD2, RED2 - VMALHF M1, MK0, ADD2, RED2H - - VSLDB $12, RED2, RED1, RED1 - VSLDB $12, T2, RED2, RED2 - - VACCQ RED1, ADD1H, CAR1 - VAQ RED1, ADD1H, T0 - VACCQ RED1H, T0, CAR1M - VAQ RED1H, T0, T0 - - // << ready for next MK0 - - VACQ RED2, ADD2H, CAR1, T1 - VACCCQ RED2, ADD2H, CAR1, CAR1 - VACCCQ RED2H, T1, CAR1M, T2 - VACQ RED2H, T1, CAR1M, T1 - VAQ CAR1, T2, T2 - - // --------------------------------------------------- - - VZERO RED1 - VSCBIQ M0, T0, CAR1 - VSQ M0, T0, ADD1 - VSBCBIQ T1, M1, CAR1, CAR1M - VSBIQ T1, M1, CAR1, ADD2 - VSBIQ T2, RED1, CAR1M, T2 - - // what output to use, ADD2||ADD1 or T1||T0? - VSEL T0, ADD1, T2, T0 - VSEL T1, ADD2, T2, T1 - - VPDI $0x4, T0, T0, T0 - VST T0, (0*16)(res_ptr) - VPDI $0x4, T1, T1, T1 - VST T1, (1*16)(res_ptr) - RET - -#undef res_ptr -#undef x_ptr -#undef y_ptr -#undef X0 -#undef X1 -#undef Y0 -#undef Y1 -#undef M0 -#undef M1 -#undef T0 -#undef T1 -#undef T2 -#undef YDIG - -#undef ADD1 -#undef ADD1H -#undef ADD2 -#undef ADD2H -#undef RED1 -#undef RED1H -#undef RED2 -#undef RED2H -#undef CAR1 -#undef CAR1M - -#undef MK0 -#undef K0 - -// --------------------------------------- -// p256MulInternalExCrypto +// p256MulInternal // V0-V3,V30,V31 - Not Modified // V4-V15 - Volatile @@ -1068,7 +637,7 @@ TEXT ·p256OrdMul<>(SB), NOSPLIT, $0 * * Last 'group' needs to RED2||RED1 shifted less */ -TEXT p256MulInternalExCrypto<>(SB), NOSPLIT, $0-0 +TEXT p256MulInternal<>(SB), NOSPLIT, $0-0 VL 32(CPOOL), SEL1 VL 48(CPOOL), SEL2 VL 64(CPOOL), SEL3 @@ -1321,17 +890,17 @@ TEXT p256MulInternalExCrypto<>(SB), NOSPLIT, $0-0 #define Y0 V2 #define Y1 V3 -TEXT p256SqrInternalExCrypto<>(SB), NOFRAME|NOSPLIT, $0 +TEXT p256SqrInternal<>(SB), NOFRAME|NOSPLIT, $0 VLR X0, Y0 VLR X1, Y1 - BR p256MulInternalExCrypto<>(SB) + BR p256MulInternal<>(SB) #undef X0 #undef X1 #undef Y0 #undef Y1 -#define p256SubInternalExCrypto(T1, T0, X1, X0, Y1, Y0) \ +#define p256SubInternal(T1, T0, X1, X0, Y1, Y0) \ VZERO ZER \ VSCBIQ Y0, X0, CAR1 \ VSQ Y0, X0, T0 \ @@ -1422,7 +991,7 @@ TEXT ·p256Mul(SB), NOSPLIT, $0 VL 16(CPOOL), P0 VL 0(CPOOL), P1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VPDI $0x4, T0, T0, T0 VST T0, (0*16)(res_ptr) @@ -1478,7 +1047,7 @@ TEXT ·p256Sqr(SB), NOSPLIT, $0 VL 0(CPOOL), P1 loop: - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) VLR T0, X0 VLR T1, X1 ADDW $1, COUNT @@ -1648,12 +1217,12 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VPDI $0x4, X0, X0, X0 VLR X0, Y0 VLR X1, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // X=T ; Y- ; MUL; T2=T // T2 = T1*Z1 T1 T2 VLR T0, X0 VLR T1, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T2L VLR T1, T2H @@ -1662,7 +1231,7 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VPDI $0x4, Y1, Y1, Y1 VL 0(P2ptr), Y0 // X2L VPDI $0x4, Y0, Y0, Y0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T1L VLR T1, T1H @@ -1671,28 +1240,28 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VLR T2H, X1 VLR Y2L, Y0 VLR Y2H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T2(SB) + CALL p256MulInternal<>(SB) // VST T1, 64(P3ptr) // VST T0, 80(P3ptr) @@ -1702,12 +1271,12 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 // X=Y; Y- ; MUL; X=T // T3 = T1*T1 T2 VLR Y0, X0 VLR Y1, X1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) VLR T0, X0 VLR T1, X1 // X- ; Y- ; MUL; T4=T // T4 = T3*T1 T2 T4 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T4L VLR T1, T4H @@ -1716,7 +1285,7 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VPDI $0x4, Y1, Y1, Y1 VL 0(P1ptr), Y0 // X1L VPDI $0x4, Y0, Y0, Y0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T3L VLR T1, T3H @@ -1728,21 +1297,21 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VLR T2H, X1 VLR T2L, Y0 VLR T2H, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // SUB(T(SB) + CALL p256MulInternal<>(SB) VLR T0, T3L VLR T1, T3H @@ -1753,10 +1322,10 @@ TEXT ·p256PointAddAffineAsm(SB), NOSPLIT, $0 VPDI $0x4, Y1, Y1, Y1 VL 32(P1ptr), Y0 // Y1L VPDI $0x4, Y0, Y0, Y0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T(SB) + CALL p256SqrInternal<>(SB) // SUB(X(SB) + CALL p256MulInternal<>(SB) // ADD(T2(SB) + CALL p256MulInternal<>(SB) VPDI $0x4, T1, T1, TT1 VST TT1, 80(P3ptr) VPDI $0x4, T0, T0, TT0 @@ -2017,7 +1586,7 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $0 // X- ; Y=X ; MUL; T- // Y3 = Y3² VLR X0, Y0 VLR X1, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // X=T ; Y=X1; MUL; T3=T // T3 = Y3*X1 VLR T0, X0 @@ -2026,14 +1595,14 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $0 VPDI $0x4, Y1, Y1, Y1 VL 0(P1ptr), Y0 VPDI $0x4, Y0, Y0, Y0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T3L VLR T1, T3H // X- ; Y=X ; MUL; T- // Y3 = Y3² VLR X0, Y0 VLR X1, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // HAL(Y3(SB) + CALL p256SqrInternal<>(SB) // ADD(T1(SB) + CALL p256MulInternal<>(SB) // SUB(Y3(SB) + CALL p256SqrInternal<>(SB) // X- ; Y=T ; MUL; R=T // R = Z1*T1 VLR T0, Y0 VLR T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, RL VLR T1, RH @@ -2244,7 +1813,7 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VPDI $0x4, X1, X1, X1 VL 0(P2ptr), X0 // X2L VPDI $0x4, X0, X0, X0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, HL VLR T1, HH @@ -2255,12 +1824,12 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VPDI $0x4, X0, X0, X0 VLR X0, Y0 VLR X1, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // X- ; Y=T ; MUL; S1=T // S1 = Z2*T2 VLR T0, Y0 VLR T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, S1L VLR T1, S1H @@ -2269,12 +1838,12 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VPDI $0x4, X1, X1, X1 VL 0(P1ptr), X0 // X1L VPDI $0x4, X0, X0, X0 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, U1L VLR T1, U1H // SUB(H(SB) + CALL p256MulInternal<>(SB) // X=T ; Y=H ; MUL; Z3:=T// Z3 = Z3*H VLR T0, X0 VLR T1, X1 VLR HL, Y0 VLR HH, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VPDI $0x4, T1, T1, TT1 VST TT1, 80(P3ptr) VPDI $0x4, T0, T0, TT0 @@ -2320,7 +1889,7 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VPDI $0x4, X0, X0, X0 VLR S1L, Y0 VLR S1H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, S1L VLR T1, S1H @@ -2331,10 +1900,10 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VPDI $0x4, X0, X0, X0 VLR RL, Y0 VLR RH, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(R(SB) + CALL p256SqrInternal<>(SB) // X- ; Y=T ; MUL; T2=T // T2 = H*T1 VLR T0, Y0 VLR T1, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, T2L VLR T1, T2H // X=U1; Y- ; MUL; U1=T // U1 = U1*T1 VLR U1L, X0 VLR U1H, X1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) VLR T0, U1L VLR T1, U1H @@ -2378,28 +1947,28 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VLR RH, X1 VLR RL, Y0 VLR RH, Y1 - CALL p256SqrInternalExCrypto<>(SB) + CALL p256SqrInternal<>(SB) // SUB(T(SB) + CALL p256MulInternal<>(SB) VLR T0, U1L VLR T1, U1H @@ -2408,10 +1977,10 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0 VLR S1H, X1 VLR T2L, Y0 VLR T2H, Y1 - CALL p256MulInternalExCrypto<>(SB) + CALL p256MulInternal<>(SB) // SUB(T maxBlocks { + return nil, errors.New("pbkdf2: keyLength too long") + } + + var buf [4]byte + dk := make([]byte, 0, numBlocks*hashLen) + U := make([]byte, hashLen) + for block := 1; block <= numBlocks; block++ { + // N.B.: || means concatenation, ^ means XOR + // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter + // U_1 = PRF(password, salt || uint(i)) + prf.Reset() + prf.Write(salt) + buf[0] = byte(block >> 24) + buf[1] = byte(block >> 16) + buf[2] = byte(block >> 8) + buf[3] = byte(block) + prf.Write(buf[:4]) + dk = prf.Sum(dk) + T := dk[len(dk)-hashLen:] + copy(U, T) + + // U_n = PRF(password, U_(n-1)) + for n := 2; n <= iter; n++ { + prf.Reset() + prf.Write(U) + U = U[:0] + U = prf.Sum(U) + for x := range U { + T[x] ^= U[x] + } + } + } + return dk[:keyLength], nil +} + +func setServiceIndicator(salt []byte, keyLength int) { + // The HMAC construction will handle the hash function considerations for the service + // indicator. The remaining PBKDF2 considerations outlined by SP 800-132 pertain to + // salt and keyLength. + + // The length of the randomly-generated portion of the salt shall be at least 128 bits. + if len(salt) < 128/8 { + fips140.RecordNonApproved() + } + + // Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for + // legacy use (i.e. verification only) and we don't support that. + if keyLength < 112/8 { + fips140.RecordNonApproved() + } + + fips140.RecordApproved() +} diff --git a/crypto/internal/fips140/rsa/cast.go b/crypto/internal/fips140/rsa/cast.go new file mode 100644 index 00000000000..0acacd03184 --- /dev/null +++ b/crypto/internal/fips140/rsa/cast.go @@ -0,0 +1,236 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "errors" + "sync" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" +) + +func testPrivateKey() *PrivateKey { + // https://www.rfc-editor.org/rfc/rfc9500.html#section-2.1 + N, _ := bigmod.NewModulus([]byte{ + 0xB0, 0xF9, 0xE8, 0x19, 0x43, 0xA7, 0xAE, 0x98, + 0x92, 0xAA, 0xDE, 0x17, 0xCA, 0x7C, 0x40, 0xF8, + 0x74, 0x4F, 0xED, 0x2F, 0x81, 0x48, 0xE6, 0xC8, + 0xEA, 0xA2, 0x7B, 0x7D, 0x00, 0x15, 0x48, 0xFB, + 0x51, 0x92, 0xAB, 0x28, 0xB5, 0x6C, 0x50, 0x60, + 0xB1, 0x18, 0xCC, 0xD1, 0x31, 0xE5, 0x94, 0x87, + 0x4C, 0x6C, 0xA9, 0x89, 0xB5, 0x6C, 0x27, 0x29, + 0x6F, 0x09, 0xFB, 0x93, 0xA0, 0x34, 0xDF, 0x32, + 0xE9, 0x7C, 0x6F, 0xF0, 0x99, 0x8C, 0xFD, 0x8E, + 0x6F, 0x42, 0xDD, 0xA5, 0x8A, 0xCD, 0x1F, 0xA9, + 0x79, 0x86, 0xF1, 0x44, 0xF3, 0xD1, 0x54, 0xD6, + 0x76, 0x50, 0x17, 0x5E, 0x68, 0x54, 0xB3, 0xA9, + 0x52, 0x00, 0x3B, 0xC0, 0x68, 0x87, 0xB8, 0x45, + 0x5A, 0xC2, 0xB1, 0x9F, 0x7B, 0x2F, 0x76, 0x50, + 0x4E, 0xBC, 0x98, 0xEC, 0x94, 0x55, 0x71, 0xB0, + 0x78, 0x92, 0x15, 0x0D, 0xDC, 0x6A, 0x74, 0xCA, + 0x0F, 0xBC, 0xD3, 0x54, 0x97, 0xCE, 0x81, 0x53, + 0x4D, 0xAF, 0x94, 0x18, 0x84, 0x4B, 0x13, 0xAE, + 0xA3, 0x1F, 0x9D, 0x5A, 0x6B, 0x95, 0x57, 0xBB, + 0xDF, 0x61, 0x9E, 0xFD, 0x4E, 0x88, 0x7F, 0x2D, + 0x42, 0xB8, 0xDD, 0x8B, 0xC9, 0x87, 0xEA, 0xE1, + 0xBF, 0x89, 0xCA, 0xB8, 0x5E, 0xE2, 0x1E, 0x35, + 0x63, 0x05, 0xDF, 0x6C, 0x07, 0xA8, 0x83, 0x8E, + 0x3E, 0xF4, 0x1C, 0x59, 0x5D, 0xCC, 0xE4, 0x3D, + 0xAF, 0xC4, 0x91, 0x23, 0xEF, 0x4D, 0x8A, 0xBB, + 0xA9, 0x3D, 0x39, 0x05, 0xE4, 0x02, 0x8D, 0x7B, + 0xA9, 0x14, 0x84, 0xA2, 0x75, 0x96, 0xE0, 0x7B, + 0x4B, 0x6E, 0xD9, 0x92, 0xF0, 0x77, 0xB5, 0x24, + 0xD3, 0xDC, 0xFE, 0x7D, 0xDD, 0x55, 0x49, 0xBE, + 0x7C, 0xCE, 0x8D, 0xA0, 0x35, 0xCF, 0xA0, 0xB3, + 0xFB, 0x8F, 0x9E, 0x46, 0xF7, 0x32, 0xB2, 0xA8, + 0x6B, 0x46, 0x01, 0x65, 0xC0, 0x8F, 0x53, 0x13}) + d, _ := bigmod.NewNat().SetBytes([]byte{ + 0x41, 0x18, 0x8B, 0x20, 0xCF, 0xDB, 0xDB, 0xC2, + 0xCF, 0x1F, 0xFE, 0x75, 0x2D, 0xCB, 0xAA, 0x72, + 0x39, 0x06, 0x35, 0x2E, 0x26, 0x15, 0xD4, 0x9D, + 0xCE, 0x80, 0x59, 0x7F, 0xCF, 0x0A, 0x05, 0x40, + 0x3B, 0xEF, 0x00, 0xFA, 0x06, 0x51, 0x82, 0xF7, + 0x2D, 0xEC, 0xFB, 0x59, 0x6F, 0x4B, 0x0C, 0xE8, + 0xFF, 0x59, 0x70, 0xBA, 0xF0, 0x7A, 0x89, 0xA5, + 0x19, 0xEC, 0xC8, 0x16, 0xB2, 0xF4, 0xFF, 0xAC, + 0x50, 0x69, 0xAF, 0x1B, 0x06, 0xBF, 0xEF, 0x7B, + 0xF6, 0xBC, 0xD7, 0x9E, 0x4E, 0x81, 0xC8, 0xC5, + 0xA3, 0xA7, 0xD9, 0x13, 0x0D, 0xC3, 0xCF, 0xBA, + 0xDA, 0xE5, 0xF6, 0xD2, 0x88, 0xF9, 0xAE, 0xE3, + 0xF6, 0xFF, 0x92, 0xFA, 0xE0, 0xF8, 0x1A, 0xF5, + 0x97, 0xBE, 0xC9, 0x6A, 0xE9, 0xFA, 0xB9, 0x40, + 0x2C, 0xD5, 0xFE, 0x41, 0xF7, 0x05, 0xBE, 0xBD, + 0xB4, 0x7B, 0xB7, 0x36, 0xD3, 0xFE, 0x6C, 0x5A, + 0x51, 0xE0, 0xE2, 0x07, 0x32, 0xA9, 0x7B, 0x5E, + 0x46, 0xC1, 0xCB, 0xDB, 0x26, 0xD7, 0x48, 0x54, + 0xC6, 0xB6, 0x60, 0x4A, 0xED, 0x46, 0x37, 0x35, + 0xFF, 0x90, 0x76, 0x04, 0x65, 0x57, 0xCA, 0xF9, + 0x49, 0xBF, 0x44, 0x88, 0x95, 0xC2, 0x04, 0x32, + 0xC1, 0xE0, 0x9C, 0x01, 0x4E, 0xA7, 0x56, 0x60, + 0x43, 0x4F, 0x1A, 0x0F, 0x3B, 0xE2, 0x94, 0xBA, + 0xBC, 0x5D, 0x53, 0x0E, 0x6A, 0x10, 0x21, 0x3F, + 0x53, 0xB6, 0x03, 0x75, 0xFC, 0x84, 0xA7, 0x57, + 0x3F, 0x2A, 0xF1, 0x21, 0x55, 0x84, 0xF5, 0xB4, + 0xBD, 0xA6, 0xD4, 0xE8, 0xF9, 0xE1, 0x7A, 0x78, + 0xD9, 0x7E, 0x77, 0xB8, 0x6D, 0xA4, 0xA1, 0x84, + 0x64, 0x75, 0x31, 0x8A, 0x7A, 0x10, 0xA5, 0x61, + 0x01, 0x4E, 0xFF, 0xA2, 0x3A, 0x81, 0xEC, 0x56, + 0xE9, 0xE4, 0x10, 0x9D, 0xEF, 0x8C, 0xB3, 0xF7, + 0x97, 0x22, 0x3F, 0x7D, 0x8D, 0x0D, 0x43, 0x51}, N) + p, _ := bigmod.NewModulus([]byte{ + 0xDD, 0x10, 0x57, 0x02, 0x38, 0x2F, 0x23, 0x2B, + 0x36, 0x81, 0xF5, 0x37, 0x91, 0xE2, 0x26, 0x17, + 0xC7, 0xBF, 0x4E, 0x9A, 0xCB, 0x81, 0xED, 0x48, + 0xDA, 0xF6, 0xD6, 0x99, 0x5D, 0xA3, 0xEA, 0xB6, + 0x42, 0x83, 0x9A, 0xFF, 0x01, 0x2D, 0x2E, 0xA6, + 0x28, 0xB9, 0x0A, 0xF2, 0x79, 0xFD, 0x3E, 0x6F, + 0x7C, 0x93, 0xCD, 0x80, 0xF0, 0x72, 0xF0, 0x1F, + 0xF2, 0x44, 0x3B, 0x3E, 0xE8, 0xF2, 0x4E, 0xD4, + 0x69, 0xA7, 0x96, 0x13, 0xA4, 0x1B, 0xD2, 0x40, + 0x20, 0xF9, 0x2F, 0xD1, 0x10, 0x59, 0xBD, 0x1D, + 0x0F, 0x30, 0x1B, 0x5B, 0xA7, 0xA9, 0xD3, 0x63, + 0x7C, 0xA8, 0xD6, 0x5C, 0x1A, 0x98, 0x15, 0x41, + 0x7D, 0x8E, 0xAB, 0x73, 0x4B, 0x0B, 0x4F, 0x3A, + 0x2C, 0x66, 0x1D, 0x9A, 0x1A, 0x82, 0xF3, 0xAC, + 0x73, 0x4C, 0x40, 0x53, 0x06, 0x69, 0xAB, 0x8E, + 0x47, 0x30, 0x45, 0xA5, 0x8E, 0x65, 0x53, 0x9D}) + q, _ := bigmod.NewModulus([]byte{ + 0xCC, 0xF1, 0xE5, 0xBB, 0x90, 0xC8, 0xE9, 0x78, + 0x1E, 0xA7, 0x5B, 0xEB, 0xF1, 0x0B, 0xC2, 0x52, + 0xE1, 0x1E, 0xB0, 0x23, 0xA0, 0x26, 0x0F, 0x18, + 0x87, 0x55, 0x2A, 0x56, 0x86, 0x3F, 0x4A, 0x64, + 0x21, 0xE8, 0xC6, 0x00, 0xBF, 0x52, 0x3D, 0x6C, + 0xB1, 0xB0, 0xAD, 0xBD, 0xD6, 0x5B, 0xFE, 0xE4, + 0xA8, 0x8A, 0x03, 0x7E, 0x3D, 0x1A, 0x41, 0x5E, + 0x5B, 0xB9, 0x56, 0x48, 0xDA, 0x5A, 0x0C, 0xA2, + 0x6B, 0x54, 0xF4, 0xA6, 0x39, 0x48, 0x52, 0x2C, + 0x3D, 0x5F, 0x89, 0xB9, 0x4A, 0x72, 0xEF, 0xFF, + 0x95, 0x13, 0x4D, 0x59, 0x40, 0xCE, 0x45, 0x75, + 0x8F, 0x30, 0x89, 0x80, 0x90, 0x89, 0x56, 0x58, + 0x8E, 0xEF, 0x57, 0x5B, 0x3E, 0x4B, 0xC4, 0xC3, + 0x68, 0xCF, 0xE8, 0x13, 0xEE, 0x9C, 0x25, 0x2C, + 0x2B, 0x02, 0xE0, 0xDF, 0x91, 0xF1, 0xAA, 0x01, + 0x93, 0x8D, 0x38, 0x68, 0x5D, 0x60, 0xBA, 0x6F}) + qInv, _ := bigmod.NewNat().SetBytes([]byte{ + 0x0A, 0x81, 0xD8, 0xA6, 0x18, 0x31, 0x4A, 0x80, + 0x3A, 0xF6, 0x1C, 0x06, 0x71, 0x1F, 0x2C, 0x39, + 0xB2, 0x66, 0xFF, 0x41, 0x4D, 0x53, 0x47, 0x6D, + 0x1D, 0xA5, 0x2A, 0x43, 0x18, 0xAA, 0xFE, 0x4B, + 0x96, 0xF0, 0xDA, 0x07, 0x15, 0x5F, 0x8A, 0x51, + 0x34, 0xDA, 0xB8, 0x8E, 0xE2, 0x9E, 0x81, 0x68, + 0x07, 0x6F, 0xCD, 0x78, 0xCA, 0x79, 0x1A, 0xC6, + 0x34, 0x42, 0xA8, 0x1C, 0xD0, 0x69, 0x39, 0x27, + 0xD8, 0x08, 0xE3, 0x35, 0xE8, 0xD8, 0xCB, 0xF2, + 0x12, 0x19, 0x07, 0x50, 0x9A, 0x57, 0x75, 0x9B, + 0x4F, 0x9A, 0x18, 0xFA, 0x3A, 0x7B, 0x33, 0x37, + 0x79, 0xED, 0xDE, 0x7A, 0x45, 0x93, 0x84, 0xF8, + 0x44, 0x4A, 0xDA, 0xEC, 0xFF, 0xEC, 0x95, 0xFD, + 0x55, 0x2B, 0x0C, 0xFC, 0xB6, 0xC7, 0xF6, 0x92, + 0x62, 0x6D, 0xDE, 0x1E, 0xF2, 0x68, 0xA4, 0x0D, + 0x2F, 0x67, 0xB5, 0xC8, 0xAA, 0x38, 0x7F, 0xF7}, p) + dP := []byte{ + 0x09, 0xED, 0x54, 0xEA, 0xED, 0x98, 0xF8, 0x4C, + 0x55, 0x7B, 0x4A, 0x86, 0xBF, 0x4F, 0x57, 0x84, + 0x93, 0xDC, 0xBC, 0x6B, 0xE9, 0x1D, 0xA1, 0x89, + 0x37, 0x04, 0x04, 0xA9, 0x08, 0x72, 0x76, 0xF4, + 0xCE, 0x51, 0xD8, 0xA1, 0x00, 0xED, 0x85, 0x7D, + 0xC2, 0xB0, 0x64, 0x94, 0x74, 0xF3, 0xF1, 0x5C, + 0xD2, 0x4C, 0x54, 0xDB, 0x28, 0x71, 0x10, 0xE5, + 0x6E, 0x5C, 0xB0, 0x08, 0x68, 0x2F, 0x91, 0x68, + 0xAA, 0x81, 0xF3, 0x14, 0x58, 0xB7, 0x43, 0x1E, + 0xCC, 0x1C, 0x44, 0x90, 0x6F, 0xDA, 0x87, 0xCA, + 0x89, 0x47, 0x10, 0xC3, 0x71, 0xE9, 0x07, 0x6C, + 0x1D, 0x49, 0xFB, 0xAE, 0x51, 0x27, 0x69, 0x34, + 0xF2, 0xAD, 0x78, 0x77, 0x89, 0xF4, 0x2D, 0x0F, + 0xA0, 0xB4, 0xC9, 0x39, 0x85, 0x5D, 0x42, 0x12, + 0x09, 0x6F, 0x70, 0x28, 0x0A, 0x4E, 0xAE, 0x7C, + 0x8A, 0x27, 0xD9, 0xC8, 0xD0, 0x77, 0x2E, 0x65} + dQ := []byte{ + 0x8C, 0xB6, 0x85, 0x7A, 0x7B, 0xD5, 0x46, 0x5F, + 0x80, 0x04, 0x7E, 0x9B, 0x87, 0xBC, 0x00, 0x27, + 0x31, 0x84, 0x05, 0x81, 0xE0, 0x62, 0x61, 0x39, + 0x01, 0x2A, 0x5B, 0x50, 0x5F, 0x0A, 0x33, 0x84, + 0x7E, 0xB7, 0xB8, 0xC3, 0x28, 0x99, 0x49, 0xAD, + 0x48, 0x6F, 0x3B, 0x4B, 0x3D, 0x53, 0x9A, 0xB5, + 0xDA, 0x76, 0x30, 0x21, 0xCB, 0xC8, 0x2C, 0x1B, + 0xA2, 0x34, 0xA5, 0x66, 0x8D, 0xED, 0x08, 0x01, + 0xB8, 0x59, 0xF3, 0x43, 0xF1, 0xCE, 0x93, 0x04, + 0xE6, 0xFA, 0xA2, 0xB0, 0x02, 0xCA, 0xD9, 0xB7, + 0x8C, 0xDE, 0x5C, 0xDC, 0x2C, 0x1F, 0xB4, 0x17, + 0x1C, 0x42, 0x42, 0x16, 0x70, 0xA6, 0xAB, 0x0F, + 0x50, 0xCC, 0x4A, 0x19, 0x4E, 0xB3, 0x6D, 0x1C, + 0x91, 0xE9, 0x35, 0xBA, 0x01, 0xB9, 0x59, 0xD8, + 0x72, 0x8B, 0x9E, 0x64, 0x42, 0x6B, 0x3F, 0xC3, + 0xA7, 0x50, 0x6D, 0xEB, 0x52, 0x39, 0xA8, 0xA7} + return &PrivateKey{ + pub: PublicKey{ + N: N, E: 65537, + }, + d: d, p: p, q: q, qInv: qInv, dP: dP, dQ: dQ, + fipsApproved: true, + } + +} + +var fipsSelfTest = sync.OnceFunc(func() { + fips140.CAST("RSASSA-PKCS-v1.5 2048-bit sign and verify", func() error { + k := testPrivateKey() + hash := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + want := []byte{ + 0x16, 0x98, 0x33, 0xc7, 0x30, 0x2c, 0x0a, 0xdc, + 0x0a, 0x8d, 0x02, 0x58, 0xeb, 0xf9, 0x7d, 0xb6, + 0x2a, 0xad, 0xee, 0x63, 0x72, 0xaa, 0x37, 0x2c, + 0xb3, 0x06, 0x04, 0xdf, 0xdb, 0x2b, 0xbc, 0xb1, + 0x76, 0x3e, 0xeb, 0x87, 0xef, 0x91, 0xef, 0x74, + 0x69, 0x62, 0x27, 0xf3, 0x24, 0xf8, 0xe7, 0x0e, + 0xb2, 0x15, 0x3f, 0xa2, 0x4d, 0xe2, 0x0c, 0xd4, + 0xdc, 0x2d, 0xc1, 0x1a, 0x84, 0x7c, 0x88, 0x80, + 0xb9, 0xa9, 0x23, 0x67, 0x39, 0x2e, 0x86, 0xc0, + 0x53, 0x9b, 0xc1, 0x35, 0xb3, 0x17, 0x5e, 0x62, + 0x95, 0xd6, 0xbc, 0x2a, 0xa6, 0xb1, 0xcf, 0x8f, + 0x99, 0x43, 0x1f, 0x3d, 0xd2, 0x70, 0x3f, 0x01, + 0x37, 0x2b, 0xdd, 0x69, 0x1a, 0x5c, 0x2b, 0x04, + 0x70, 0x92, 0xea, 0x2d, 0x86, 0x00, 0xcb, 0x79, + 0xca, 0xaf, 0xa4, 0x1c, 0xd9, 0x61, 0x21, 0x3b, + 0x1e, 0xc5, 0x88, 0xfb, 0xff, 0xbd, 0xc7, 0x3c, + 0x36, 0xa1, 0xc6, 0x85, 0x03, 0xaf, 0x47, 0x4f, + 0x42, 0x9e, 0x23, 0x65, 0x24, 0x69, 0x17, 0xdb, + 0xe7, 0xb7, 0xdc, 0x51, 0xc6, 0x30, 0x40, 0x32, + 0x4f, 0x71, 0xf1, 0x62, 0x2d, 0xaa, 0x98, 0xdb, + 0x11, 0x14, 0xf9, 0x9c, 0x35, 0xc3, 0x16, 0xe1, + 0x1a, 0xd1, 0x8c, 0x4d, 0x8c, 0xad, 0x06, 0x34, + 0xd2, 0x84, 0x97, 0xa4, 0x0b, 0x6e, 0x6d, 0x19, + 0x9f, 0xa7, 0x40, 0x1e, 0xb5, 0xfc, 0x4e, 0x12, + 0x08, 0xec, 0xf4, 0x07, 0x13, 0xdc, 0x5a, 0x8c, + 0xd5, 0x2a, 0xd6, 0x5a, 0x2c, 0xc9, 0x54, 0x84, + 0x78, 0x34, 0x8f, 0x11, 0xfb, 0x6e, 0xd4, 0x27, + 0x45, 0xd9, 0xfa, 0x90, 0x82, 0x83, 0x73, 0x22, + 0x15, 0xab, 0x96, 0x13, 0x0d, 0x52, 0x1c, 0xdc, + 0x17, 0xde, 0x12, 0x6f, 0x84, 0x46, 0xbb, 0xec, + 0xe3, 0xb1, 0xa1, 0x5d, 0x8b, 0xeb, 0xe6, 0xae, + 0x02, 0xb8, 0x76, 0x47, 0x76, 0x11, 0x61, 0x2b, + } + sig, err := signPKCS1v15(k, "SHA-256", hash) + if err != nil { + return err + } + if err := verifyPKCS1v15(k.PublicKey(), "SHA-256", hash, sig); err != nil { + return err + } + if !bytes.Equal(sig, want) { + return errors.New("unexpected result") + } + return nil + }) +}) diff --git a/crypto/internal/fips140/rsa/keygen.go b/crypto/internal/fips140/rsa/keygen.go new file mode 100644 index 00000000000..8379631bb68 --- /dev/null +++ b/crypto/internal/fips140/rsa/keygen.go @@ -0,0 +1,399 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "errors" + "io" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" +) + +// GenerateKey generates a new RSA key pair of the given bit size. +// bits must be at least 32. +func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { + if bits < 32 { + return nil, errors.New("rsa: key too small") + } + fips140.RecordApproved() + if bits < 2048 || bits%2 == 1 { + fips140.RecordNonApproved() + } + + for { + p, err := randomPrime(rand, (bits+1)/2) + if err != nil { + return nil, err + } + q, err := randomPrime(rand, bits/2) + if err != nil { + return nil, err + } + + P, err := bigmod.NewModulus(p) + if err != nil { + return nil, err + } + Q, err := bigmod.NewModulus(q) + if err != nil { + return nil, err + } + + if Q.Nat().ExpandFor(P).Equal(P.Nat()) == 1 { + return nil, errors.New("rsa: generated p == q, random source is broken") + } + + N, err := bigmod.NewModulusProduct(p, q) + if err != nil { + return nil, err + } + if N.BitLen() != bits { + return nil, errors.New("rsa: internal error: modulus size incorrect") + } + + // d can be safely computed as e⁻¹ mod φ(N) where φ(N) = (p-1)(q-1), and + // indeed that's what both the original RSA paper and the pre-FIPS + // crypto/rsa implementation did. + // + // However, FIPS 186-5, A.1.1(3) requires computing it as e⁻¹ mod λ(N) + // where λ(N) = lcm(p-1, q-1). + // + // This makes d smaller by 1.5 bits on average, which is irrelevant both + // because we exclusively use the CRT for private operations and because + // we use constant time windowed exponentiation. On the other hand, it + // requires computing a GCD of two values that are not coprime, and then + // a division, both complex variable-time operations. + λ, err := totient(P, Q) + if err == errDivisorTooLarge { + // The divisor is too large, try again with different primes. + continue + } + if err != nil { + return nil, err + } + + e := bigmod.NewNat().SetUint(65537) + d, ok := bigmod.NewNat().InverseVarTime(e, λ) + if !ok { + // This checks that GCD(e, lcm(p-1, q-1)) = 1, which is equivalent + // to checking GCD(e, p-1) = 1 and GCD(e, q-1) = 1 separately in + // FIPS 186-5, Appendix A.1.3, steps 4.5 and 5.6. + // + // We waste a prime by retrying the whole process, since 65537 is + // probably only a factor of one of p-1 or q-1, but the probability + // of this check failing is only 1/65537, so it doesn't matter. + continue + } + + if e.ExpandFor(λ).Mul(d, λ).IsOne() == 0 { + return nil, errors.New("rsa: internal error: e*d != 1 mod λ(N)") + } + + // FIPS 186-5, A.1.1(3) requires checking that d > 2^(nlen / 2). + // + // The probability of this check failing when d is derived from + // (e, p, q) is roughly + // + // 2^(nlen/2) / 2^nlen = 2^(-nlen/2) + // + // so less than 2⁻¹²⁸ for keys larger than 256 bits. + // + // We still need to check to comply with FIPS 186-5, but knowing it has + // negligible chance of failure we can defer the check to the end of key + // generation and return an error if it fails. See [checkPrivateKey]. + + return newPrivateKey(N, 65537, d, P, Q) + } +} + +// errDivisorTooLarge is returned by [totient] when gcd(p-1, q-1) is too large. +var errDivisorTooLarge = errors.New("divisor too large") + +// totient computes the Carmichael totient function λ(N) = lcm(p-1, q-1). +func totient(p, q *bigmod.Modulus) (*bigmod.Modulus, error) { + a, b := p.Nat().SubOne(p), q.Nat().SubOne(q) + + // lcm(a, b) = a×b / gcd(a, b) = a × (b / gcd(a, b)) + + // Our GCD requires at least one of the numbers to be odd. For LCM we only + // need to preserve the larger prime power of each prime factor, so we can + // right-shift the number with the fewest trailing zeros until it's odd. + // For odd a, b and m >= n, lcm(a×2ᵐ, b×2ⁿ) = lcm(a×2ᵐ, b). + az, bz := a.TrailingZeroBitsVarTime(), b.TrailingZeroBitsVarTime() + if az < bz { + a = a.ShiftRightVarTime(az) + } else { + b = b.ShiftRightVarTime(bz) + } + + gcd, err := bigmod.NewNat().GCDVarTime(a, b) + if err != nil { + return nil, err + } + if gcd.IsOdd() == 0 { + return nil, errors.New("rsa: internal error: gcd(a, b) is even") + } + + // To avoid implementing multiple-precision division, we just try again if + // the divisor doesn't fit in a single word. This would have a chance of + // 2⁻⁶⁴ on 64-bit platforms, and 2⁻³² on 32-bit platforms, but testing 2⁻⁶⁴ + // edge cases is impractical, and we'd rather not behave differently on + // different platforms, so we reject divisors above 2³²-1. + if gcd.BitLenVarTime() > 32 { + return nil, errDivisorTooLarge + } + if gcd.IsZero() == 1 || gcd.Bits()[0] == 0 { + return nil, errors.New("rsa: internal error: gcd(a, b) is zero") + } + if rem := b.DivShortVarTime(gcd.Bits()[0]); rem != 0 { + return nil, errors.New("rsa: internal error: b is not divisible by gcd(a, b)") + } + + return bigmod.NewModulusProduct(a.Bytes(p), b.Bytes(q)) +} + +// randomPrime returns a random prime number of the given bit size following +// the process in FIPS 186-5, Appendix A.1.3. +func randomPrime(rand io.Reader, bits int) ([]byte, error) { + if bits < 16 { + return nil, errors.New("rsa: prime size must be at least 16 bits") + } + + b := make([]byte, (bits+7)/8) + for { + if err := drbg.ReadWithReader(rand, b); err != nil { + return nil, err + } + // Clear the most significant bits to reach the desired size. We use a + // mask rather than right-shifting b[0] to make it easier to inject test + // candidates, which can be represented as simple big-endian integers. + excess := len(b)*8 - bits + b[0] &= 0b1111_1111 >> excess + + // Don't let the value be too small: set the most significant two bits. + // Setting the top two bits, rather than just the top bit, means that + // when two of these values are multiplied together, the result isn't + // ever one bit short. + if excess < 7 { + b[0] |= 0b1100_0000 >> excess + } else { + b[0] |= 0b0000_0001 + b[1] |= 0b1000_0000 + } + + // Make the value odd since an even number certainly isn't prime. + b[len(b)-1] |= 1 + + // We don't need to check for p >= √2 × 2^(bits-1) (steps 4.4 and 5.4) + // because we set the top two bits above, so + // + // p > 2^(bits-1) + 2^(bits-2) = 3⁄2 × 2^(bits-1) > √2 × 2^(bits-1) + // + + // Step 5.5 requires checking that |p - q| > 2^(nlen/2 - 100). + // + // The probability of |p - q| ≤ k where p and q are uniformly random in + // the range (a, b) is 1 - (b-a-k)^2 / (b-a)^2, so the probability of + // this check failing during key generation is 2⁻⁹⁷. + // + // We still need to check to comply with FIPS 186-5, but knowing it has + // negligible chance of failure we can defer the check to the end of key + // generation and return an error if it fails. See [checkPrivateKey]. + + if isPrime(b) { + return b, nil + } + } +} + +// isPrime runs the Miller-Rabin Probabilistic Primality Test from +// FIPS 186-5, Appendix B.3.1. +// +// w must be a random odd integer greater than three in big-endian order. +// isPrime might return false positives for adversarially chosen values. +// +// isPrime is not constant-time. +func isPrime(w []byte) bool { + mr, err := millerRabinSetup(w) + if err != nil { + // w is zero, one, or even. + return false + } + + // Before Miller-Rabin, rule out most composites with trial divisions. + for i := 0; i < len(primes); i += 3 { + p1, p2, p3 := primes[i], primes[i+1], primes[i+2] + r := mr.w.Nat().DivShortVarTime(p1 * p2 * p3) + if r%p1 == 0 || r%p2 == 0 || r%p3 == 0 { + return false + } + } + + // iterations is the number of Miller-Rabin rounds, each with a + // randomly-selected base. + // + // The worst case false positive rate for a single iteration is 1/4 per + // https://eprint.iacr.org/2018/749, so if w were selected adversarially, we + // would need up to 64 iterations to get to a negligible (2⁻¹²⁸) chance of + // false positive. + // + // However, since this function is only used for randomly-selected w in the + // context of RSA key generation, we can use a smaller number of iterations. + // The exact number depends on the size of the prime (and the implied + // security level). See BoringSSL for the full formula. + // https://cs.opensource.google/boringssl/boringssl/+/master:crypto/fipsmodule/bn/prime.c.inc;l=208-283;drc=3a138e43 + bits := mr.w.BitLen() + var iterations int + switch { + case bits >= 3747: + iterations = 3 + case bits >= 1345: + iterations = 4 + case bits >= 476: + iterations = 5 + case bits >= 400: + iterations = 6 + case bits >= 347: + iterations = 7 + case bits >= 308: + iterations = 8 + case bits >= 55: + iterations = 27 + default: + iterations = 34 + } + + b := make([]byte, (bits+7)/8) + for { + drbg.Read(b) + excess := len(b)*8 - bits + b[0] &= 0b1111_1111 >> excess + result, err := millerRabinIteration(mr, b) + if err != nil { + // b was rejected. + continue + } + if result == millerRabinCOMPOSITE { + return false + } + iterations-- + if iterations == 0 { + return true + } + } +} + +// primes are the first prime numbers (except 2), such that the product of any +// three primes fits in a uint32. +// +// More primes cause fewer Miller-Rabin tests of composites (nothing can help +// with the final test on the actual prime) but have diminishing returns: these +// 255 primes catch 84.9% of composites, the next 255 would catch 1.5% more. +// Adding primes can still be marginally useful since they only compete with the +// (much more expensive) first Miller-Rabin round for candidates that were not +// rejected by the previous primes. +var primes = []uint{ + 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, + 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, + 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, + 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, + 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, + 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, + 1597, 1601, 1607, 1609, 1613, 1619, +} + +type millerRabin struct { + w *bigmod.Modulus + a uint + m []byte +} + +// millerRabinSetup prepares state that's reused across multiple iterations of +// the Miller-Rabin test. +func millerRabinSetup(w []byte) (*millerRabin, error) { + mr := &millerRabin{} + + // Check that w is odd, and precompute Montgomery parameters. + wm, err := bigmod.NewModulus(w) + if err != nil { + return nil, err + } + if wm.Nat().IsOdd() == 0 { + return nil, errors.New("candidate is even") + } + mr.w = wm + + // Compute m = (w-1)/2^a, where m is odd. + wMinus1 := mr.w.Nat().SubOne(mr.w) + if wMinus1.IsZero() == 1 { + return nil, errors.New("candidate is one") + } + mr.a = wMinus1.TrailingZeroBitsVarTime() + + // Store mr.m as a big-endian byte slice with leading zero bytes removed, + // for use with [bigmod.Nat.Exp]. + m := wMinus1.ShiftRightVarTime(mr.a) + mr.m = m.Bytes(mr.w) + for mr.m[0] == 0 { + mr.m = mr.m[1:] + } + + return mr, nil +} + +const millerRabinCOMPOSITE = false +const millerRabinPOSSIBLYPRIME = true + +func millerRabinIteration(mr *millerRabin, bb []byte) (bool, error) { + // Reject b ≤ 1 or b ≥ w − 1. + if len(bb) != (mr.w.BitLen()+7)/8 { + return false, errors.New("incorrect length") + } + b := bigmod.NewNat() + if _, err := b.SetBytes(bb, mr.w); err != nil { + return false, err + } + if b.IsZero() == 1 || b.IsOne() == 1 || b.IsMinusOne(mr.w) == 1 { + return false, errors.New("out-of-range candidate") + } + + // Compute b^(m*2^i) mod w for successive i. + // If b^m mod w = 1, b is a possible prime. + // If b^(m*2^i) mod w = -1 for some 0 <= i < a, b is a possible prime. + // Otherwise b is composite. + + // Start by computing and checking b^m mod w (also the i = 0 case). + z := bigmod.NewNat().Exp(b, mr.m, mr.w) + if z.IsOne() == 1 || z.IsMinusOne(mr.w) == 1 { + return millerRabinPOSSIBLYPRIME, nil + } + + // Check b^(m*2^i) mod w = -1 for 0 < i < a. + for range mr.a - 1 { + z.Mul(z, mr.w) + if z.IsMinusOne(mr.w) == 1 { + return millerRabinPOSSIBLYPRIME, nil + } + if z.IsOne() == 1 { + // Future squaring will not turn z == 1 into -1. + break + } + } + + return millerRabinCOMPOSITE, nil +} diff --git a/crypto/internal/fips140/rsa/keygen_test.go b/crypto/internal/fips140/rsa/keygen_test.go new file mode 100644 index 00000000000..e60d19733ae --- /dev/null +++ b/crypto/internal/fips140/rsa/keygen_test.go @@ -0,0 +1,182 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bufio" + "encoding/hex" + "fmt" + "math/big" + "os" + "strings" + "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" +) + +func TestMillerRabin(t *testing.T) { + f, err := os.Open("testdata/miller_rabin_tests.txt") + if err != nil { + t.Fatal(err) + } + + var expected bool + var W, B string + var lineNum int + scanner := bufio.NewScanner(f) + for scanner.Scan() { + lineNum++ + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + + k, v, _ := strings.Cut(line, " = ") + switch k { + case "Result": + switch v { + case "Composite": + expected = millerRabinCOMPOSITE + case "PossiblyPrime": + expected = millerRabinPOSSIBLYPRIME + default: + t.Fatalf("unknown result %q on line %d", v, lineNum) + } + case "W": + W = v + case "B": + B = v + + t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) { + if len(W)%2 != 0 { + W = "0" + W + } + for len(B) < len(W) { + B = "0" + B + } + + mr, err := millerRabinSetup(decodeHex(t, W)) + if err != nil { + t.Logf("W = %s", W) + t.Logf("B = %s", B) + t.Fatalf("failed to set up Miller-Rabin test: %v", err) + } + + result, err := millerRabinIteration(mr, decodeHex(t, B)) + if err != nil { + t.Logf("W = %s", W) + t.Logf("B = %s", B) + t.Fatalf("failed to run Miller-Rabin test: %v", err) + } + + if result != expected { + t.Logf("W = %s", W) + t.Logf("B = %s", B) + t.Fatalf("unexpected result: got %v, want %v", result, expected) + } + }) + default: + t.Fatalf("unknown key %q on line %d", k, lineNum) + } + } + if err := scanner.Err(); err != nil { + t.Fatal(err) + } +} + +func TestTotient(t *testing.T) { + f, err := os.Open("testdata/gcd_lcm_tests.txt") + if err != nil { + t.Fatal(err) + } + + var GCD, A, B, LCM string + var lineNum int + scanner := bufio.NewScanner(f) + for scanner.Scan() { + lineNum++ + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + + k, v, _ := strings.Cut(line, " = ") + switch k { + case "GCD": + GCD = v + case "A": + A = v + case "B": + B = v + case "LCM": + LCM = v + + t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) { + if A == "0" || B == "0" { + t.Skip("skipping test with zero input") + } + if LCM == "1" { + t.Skip("skipping test with LCM=1") + } + + p, _ := bigmod.NewModulus(addOne(decodeHex(t, A))) + a, _ := bigmod.NewNat().SetBytes(decodeHex(t, A), p) + q, _ := bigmod.NewModulus(addOne(decodeHex(t, B))) + b, _ := bigmod.NewNat().SetBytes(decodeHex(t, B), q) + + gcd, err := bigmod.NewNat().GCDVarTime(a, b) + // GCD doesn't work if a and b are both even, but LCM handles it. + if err == nil { + if got := strings.TrimLeft(hex.EncodeToString(gcd.Bytes(p)), "0"); got != GCD { + t.Fatalf("unexpected GCD: got %s, want %s", got, GCD) + } + } + + lcm, err := totient(p, q) + if oddDivisorLargerThan32Bits(decodeHex(t, GCD)) { + if err != errDivisorTooLarge { + t.Fatalf("expected divisor too large error, got %v", err) + } + t.Skip("GCD too large") + } + if err != nil { + t.Fatalf("failed to calculate totient: %v", err) + } + if got := strings.TrimLeft(hex.EncodeToString(lcm.Nat().Bytes(lcm)), "0"); got != LCM { + t.Fatalf("unexpected LCM: got %s, want %s", got, LCM) + } + }) + default: + t.Fatalf("unknown key %q on line %d", k, lineNum) + } + } + if err := scanner.Err(); err != nil { + t.Fatal(err) + } +} + +func oddDivisorLargerThan32Bits(b []byte) bool { + x := new(big.Int).SetBytes(b) + x.Rsh(x, x.TrailingZeroBits()) + return x.BitLen() > 32 +} + +func addOne(b []byte) []byte { + x := new(big.Int).SetBytes(b) + x.Add(x, big.NewInt(1)) + return x.Bytes() +} + +func decodeHex(t *testing.T, s string) []byte { + t.Helper() + if len(s)%2 != 0 { + s = "0" + s + } + b, err := hex.DecodeString(s) + if err != nil { + t.Fatalf("failed to decode hex %q: %v", s, err) + } + return b +} diff --git a/crypto/internal/fips140/rsa/pkcs1v15.go b/crypto/internal/fips140/rsa/pkcs1v15.go new file mode 100644 index 00000000000..efcdd3a73c5 --- /dev/null +++ b/crypto/internal/fips140/rsa/pkcs1v15.go @@ -0,0 +1,139 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +// This file implements signing and verification using PKCS #1 v1.5 signatures. + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +// These are ASN1 DER structures: +// +// DigestInfo ::= SEQUENCE { +// digestAlgorithm AlgorithmIdentifier, +// digest OCTET STRING +// } +// +// For performance, we don't use the generic ASN1 encoder. Rather, we +// precompute a prefix of the digest value that makes a valid ASN1 DER string +// with the correct contents. +var hashPrefixes = map[string][]byte{ + "MD5": {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, + "SHA-1": {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, + "SHA-224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, + "SHA-256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, + "SHA-384": {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, + "SHA-512": {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, + "SHA-512/224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1C}, + "SHA-512/256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20}, + "SHA3-224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1C}, + "SHA3-256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20}, + "SHA3-384": {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30}, + "SHA3-512": {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40}, + "MD5+SHA1": {}, // A special TLS case which doesn't use an ASN1 prefix. + "RIPEMD-160": {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, +} + +// SignPKCS1v15 calculates an RSASSA-PKCS1-v1.5 signature. +// +// hash is the name of the hash function as returned by [crypto.Hash.String] +// or the empty string to indicate that the message is signed directly. +func SignPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) { + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHashName(hash) + + return signPKCS1v15(priv, hash, hashed) +} + +func signPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) { + em, err := pkcs1v15ConstructEM(&priv.pub, hash, hashed) + if err != nil { + return nil, err + } + + return decrypt(priv, em, withCheck) +} + +func pkcs1v15ConstructEM(pub *PublicKey, hash string, hashed []byte) ([]byte, error) { + // Special case: "" is used to indicate that the data is signed directly. + var prefix []byte + if hash != "" { + var ok bool + prefix, ok = hashPrefixes[hash] + if !ok { + return nil, errors.New("crypto/rsa: unsupported hash function") + } + } + + // EM = 0x00 || 0x01 || PS || 0x00 || T + k := pub.Size() + if k < len(prefix)+len(hashed)+2+8+1 { + return nil, ErrMessageTooLong + } + em := make([]byte, k) + em[1] = 1 + for i := 2; i < k-len(prefix)-len(hashed)-1; i++ { + em[i] = 0xff + } + copy(em[k-len(prefix)-len(hashed):], prefix) + copy(em[k-len(hashed):], hashed) + return em, nil +} + +// VerifyPKCS1v15 verifies an RSASSA-PKCS1-v1.5 signature. +// +// hash is the name of the hash function as returned by [crypto.Hash.String] +// or the empty string to indicate that the message is signed directly. +func VerifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error { + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHashName(hash) + + return verifyPKCS1v15(pub, hash, hashed, sig) +} + +func verifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error { + if fipsApproved, err := checkPublicKey(pub); err != nil { + return err + } else if !fipsApproved { + fips140.RecordNonApproved() + } + + // RFC 8017 Section 8.2.2: If the length of the signature S is not k + // octets (where k is the length in octets of the RSA modulus n), output + // "invalid signature" and stop. + if pub.Size() != len(sig) { + return ErrVerification + } + + em, err := encrypt(pub, sig) + if err != nil { + return ErrVerification + } + + expected, err := pkcs1v15ConstructEM(pub, hash, hashed) + if err != nil { + return ErrVerification + } + if !bytes.Equal(em, expected) { + return ErrVerification + } + + return nil +} + +func checkApprovedHashName(hash string) { + switch hash { + case "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256", + "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512": + default: + fips140.RecordNonApproved() + } +} diff --git a/crypto/internal/fips140/rsa/pkcs1v15_test.go b/crypto/internal/fips140/rsa/pkcs1v15_test.go new file mode 100644 index 00000000000..af516e7a579 --- /dev/null +++ b/crypto/internal/fips140/rsa/pkcs1v15_test.go @@ -0,0 +1,77 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "testing" + + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/x509/pkix" + "github.com/runZeroInc/excrypto/encoding/asn1" +) + +func TestHashPrefixes(t *testing.T) { + prefixes := map[crypto.Hash]asn1.ObjectIdentifier{ + // RFC 3370, Section 2.1 and 2.2 + // + // sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + // oiw(14) secsig(3) algorithm(2) 26 } + // + // md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + // rsadsi(113549) digestAlgorithm(2) 5 } + crypto.MD5: {1, 2, 840, 113549, 2, 5}, + crypto.SHA1: {1, 3, 14, 3, 2, 26}, + + // https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration + // + // nistAlgorithms OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) country(16) us(840) + // organization(1) gov(101) csor(3) nistAlgorithm(4) } + // + // hashAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 2 } + // + // id-sha256 OBJECT IDENTIFIER ::= { hashAlgs 1 } + // id-sha384 OBJECT IDENTIFIER ::= { hashAlgs 2 } + // id-sha512 OBJECT IDENTIFIER ::= { hashAlgs 3 } + // id-sha224 OBJECT IDENTIFIER ::= { hashAlgs 4 } + // id-sha512-224 OBJECT IDENTIFIER ::= { hashAlgs 5 } + // id-sha512-256 OBJECT IDENTIFIER ::= { hashAlgs 6 } + // id-sha3-224 OBJECT IDENTIFIER ::= { hashAlgs 7 } + // id-sha3-256 OBJECT IDENTIFIER ::= { hashAlgs 8 } + // id-sha3-384 OBJECT IDENTIFIER ::= { hashAlgs 9 } + // id-sha3-512 OBJECT IDENTIFIER ::= { hashAlgs 10 } + crypto.SHA224: {2, 16, 840, 1, 101, 3, 4, 2, 4}, + crypto.SHA256: {2, 16, 840, 1, 101, 3, 4, 2, 1}, + crypto.SHA384: {2, 16, 840, 1, 101, 3, 4, 2, 2}, + crypto.SHA512: {2, 16, 840, 1, 101, 3, 4, 2, 3}, + crypto.SHA512_224: {2, 16, 840, 1, 101, 3, 4, 2, 5}, + crypto.SHA512_256: {2, 16, 840, 1, 101, 3, 4, 2, 6}, + crypto.SHA3_224: {2, 16, 840, 1, 101, 3, 4, 2, 7}, + crypto.SHA3_256: {2, 16, 840, 1, 101, 3, 4, 2, 8}, + crypto.SHA3_384: {2, 16, 840, 1, 101, 3, 4, 2, 9}, + crypto.SHA3_512: {2, 16, 840, 1, 101, 3, 4, 2, 10}, + } + + for h, oid := range prefixes { + want, err := asn1.Marshal(struct { + HashAlgorithm pkix.AlgorithmIdentifier + Hash []byte + }{ + HashAlgorithm: pkix.AlgorithmIdentifier{ + Algorithm: oid, + Parameters: asn1.NullRawValue, + }, + Hash: make([]byte, h.Size()), + }) + if err != nil { + t.Fatal(err) + } + want = want[:len(want)-h.Size()] + got := hashPrefixes[h.String()] + if !bytes.Equal(got, want) { + t.Errorf("%s: got %x, want %x", h, got, want) + } + } +} diff --git a/crypto/internal/fips140/rsa/pkcs1v22.go b/crypto/internal/fips140/rsa/pkcs1v22.go new file mode 100644 index 00000000000..95985ef467d --- /dev/null +++ b/crypto/internal/fips140/rsa/pkcs1v22.go @@ -0,0 +1,475 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +// This file implements the RSASSA-PSS signature scheme and the RSAES-OAEP +// encryption scheme according to RFC 8017, aka PKCS #1 v2.2. + +import ( + "bytes" + "errors" + "io" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" +) + +// Per RFC 8017, Section 9.1 +// +// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc +// +// where +// +// DB = PS || 0x01 || salt +// +// and PS can be empty so +// +// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2 +// + +// incCounter increments a four byte, big-endian counter. +func incCounter(c *[4]byte) { + if c[3]++; c[3] != 0 { + return + } + if c[2]++; c[2] != 0 { + return + } + if c[1]++; c[1] != 0 { + return + } + c[0]++ +} + +// mgf1XOR XORs the bytes in out with a mask generated using the MGF1 function +// specified in PKCS #1 v2.1. +func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { + var counter [4]byte + var digest []byte + + done := 0 + for done < len(out) { + hash.Reset() + hash.Write(seed) + hash.Write(counter[0:4]) + digest = hash.Sum(digest[:0]) + + for i := 0; i < len(digest) && done < len(out); i++ { + out[done] ^= digest[i] + done++ + } + incCounter(&counter) + } +} + +func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { + // See RFC 8017, Section 9.1.1. + + hLen := hash.Size() + sLen := len(salt) + emLen := (emBits + 7) / 8 + + // 1. If the length of M is greater than the input limitation for the + // hash function (2^61 - 1 octets for SHA-1), output "message too + // long" and stop. + // + // 2. Let mHash = Hash(M), an octet string of length hLen. + + if len(mHash) != hLen { + return nil, errors.New("crypto/rsa: input must be hashed with given hash") + } + + // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. + + if emLen < hLen+sLen+2 { + return nil, ErrMessageTooLong + } + + em := make([]byte, emLen) + psLen := emLen - sLen - hLen - 2 + db := em[:psLen+1+sLen] + h := em[psLen+1+sLen : emLen-1] + + // 4. Generate a random octet string salt of length sLen; if sLen = 0, + // then salt is the empty string. + // + // 5. Let + // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; + // + // M' is an octet string of length 8 + hLen + sLen with eight + // initial zero octets. + // + // 6. Let H = Hash(M'), an octet string of length hLen. + + var prefix [8]byte + + hash.Reset() + hash.Write(prefix[:]) + hash.Write(mHash) + hash.Write(salt) + + h = hash.Sum(h[:0]) + + // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 + // zero octets. The length of PS may be 0. + // + // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length + // emLen - hLen - 1. + + db[psLen] = 0x01 + copy(db[psLen+1:], salt) + + // 9. Let dbMask = MGF(H, emLen - hLen - 1). + // + // 10. Let maskedDB = DB \xor dbMask. + + mgf1XOR(db, hash, h) + + // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in + // maskedDB to zero. + + db[0] &= 0xff >> (8*emLen - emBits) + + // 12. Let EM = maskedDB || H || 0xbc. + em[emLen-1] = 0xbc + + // 13. Output EM. + return em, nil +} + +const pssSaltLengthAutodetect = -1 + +func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { + // See RFC 8017, Section 9.1.2. + + hLen := hash.Size() + emLen := (emBits + 7) / 8 + if emLen != len(em) { + return errors.New("rsa: internal error: inconsistent length") + } + + // 1. If the length of M is greater than the input limitation for the + // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" + // and stop. + // + // 2. Let mHash = Hash(M), an octet string of length hLen. + if hLen != len(mHash) { + return ErrVerification + } + + // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. + if emLen < hLen+sLen+2 { + return ErrVerification + } + + // 4. If the rightmost octet of EM does not have hexadecimal value + // 0xbc, output "inconsistent" and stop. + if em[emLen-1] != 0xbc { + return ErrVerification + } + + // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and + // let H be the next hLen octets. + db := em[:emLen-hLen-1] + h := em[emLen-hLen-1 : emLen-1] + + // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in + // maskedDB are not all equal to zero, output "inconsistent" and + // stop. + var bitMask byte = 0xff >> (8*emLen - emBits) + if em[0] & ^bitMask != 0 { + return ErrVerification + } + + // 7. Let dbMask = MGF(H, emLen - hLen - 1). + // + // 8. Let DB = maskedDB \xor dbMask. + mgf1XOR(db, hash, h) + + // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB + // to zero. + db[0] &= bitMask + + // If we don't know the salt length, look for the 0x01 delimiter. + if sLen == pssSaltLengthAutodetect { + psLen := bytes.IndexByte(db, 0x01) + if psLen < 0 { + return ErrVerification + } + sLen = len(db) - psLen - 1 + } + + // FIPS 186-5, Section 5.4(g): "the length (in bytes) of the salt (sLen) + // shall satisfy 0 ≤ sLen ≤ hLen". + if sLen > hLen { + fips140.RecordNonApproved() + } + + // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero + // or if the octet at position emLen - hLen - sLen - 1 (the leftmost + // position is "position 1") does not have hexadecimal value 0x01, + // output "inconsistent" and stop. + psLen := emLen - hLen - sLen - 2 + for _, e := range db[:psLen] { + if e != 0x00 { + return ErrVerification + } + } + if db[psLen] != 0x01 { + return ErrVerification + } + + // 11. Let salt be the last sLen octets of DB. + salt := db[len(db)-sLen:] + + // 12. Let + // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; + // M' is an octet string of length 8 + hLen + sLen with eight + // initial zero octets. + // + // 13. Let H' = Hash(M'), an octet string of length hLen. + hash.Reset() + var prefix [8]byte + hash.Write(prefix[:]) + hash.Write(mHash) + hash.Write(salt) + + h0 := hash.Sum(nil) + + // 14. If H = H', output "consistent." Otherwise, output "inconsistent." + if !bytes.Equal(h0, h) { + return ErrVerification + } + return nil +} + +// PSSMaxSaltLength returns the maximum salt length for a given public key and +// hash function. +func PSSMaxSaltLength(pub *PublicKey, hash hash.Hash) (int, error) { + saltLength := (pub.N.BitLen()-1+7)/8 - 2 - hash.Size() + if saltLength < 0 { + return 0, ErrMessageTooLong + } + // FIPS 186-5, Section 5.4(g): "the length (in bytes) of the salt (sLen) + // shall satisfy 0 ≤ sLen ≤ hLen". + if fips140.Enabled && saltLength > hash.Size() { + return hash.Size(), nil + } + return saltLength, nil +} + +// SignPSS calculates the signature of hashed using RSASSA-PSS. +func SignPSS(rand io.Reader, priv *PrivateKey, hash hash.Hash, hashed []byte, saltLength int) ([]byte, error) { + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHash(hash) + + // Note that while we don't commit to deterministic execution with respect + // to the rand stream, we also don't apply MaybeReadByte, so per Hyrum's Law + // it's probably relied upon by some. It's a tolerable promise because a + // well-specified number of random bytes is included in the signature, in a + // well-specified way. + + if saltLength < 0 { + return nil, errors.New("crypto/rsa: salt length cannot be negative") + } + // FIPS 186-5, Section 5.4(g): "the length (in bytes) of the salt (sLen) + // shall satisfy 0 ≤ sLen ≤ hLen". + if saltLength > hash.Size() { + fips140.RecordNonApproved() + } + salt := make([]byte, saltLength) + if err := drbg.ReadWithReaderDeterministic(rand, salt); err != nil { + return nil, err + } + + emBits := priv.pub.N.BitLen() - 1 + em, err := emsaPSSEncode(hashed, emBits, salt, hash) + if err != nil { + return nil, err + } + + // RFC 8017: "Note that the octet length of EM will be one less than k if + // modBits - 1 is divisible by 8 and equal to k otherwise, where k is the + // length in octets of the RSA modulus n." 🙄 + // + // This is extremely annoying, as all other encrypt and decrypt inputs are + // always the exact same size as the modulus. Since it only happens for + // weird modulus sizes, fix it by padding inefficiently. + if emLen, k := len(em), priv.pub.Size(); emLen < k { + emNew := make([]byte, k) + copy(emNew[k-emLen:], em) + em = emNew + } + + return decrypt(priv, em, withCheck) +} + +// VerifyPSS verifies sig with RSASSA-PSS automatically detecting the salt length. +func VerifyPSS(pub *PublicKey, hash hash.Hash, digest []byte, sig []byte) error { + return verifyPSS(pub, hash, digest, sig, pssSaltLengthAutodetect) +} + +// VerifyPSS verifies sig with RSASSA-PSS and an expected salt length. +func VerifyPSSWithSaltLength(pub *PublicKey, hash hash.Hash, digest []byte, sig []byte, saltLength int) error { + if saltLength < 0 { + return errors.New("crypto/rsa: salt length cannot be negative") + } + return verifyPSS(pub, hash, digest, sig, saltLength) +} + +func verifyPSS(pub *PublicKey, hash hash.Hash, digest []byte, sig []byte, saltLength int) error { + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHash(hash) + if fipsApproved, err := checkPublicKey(pub); err != nil { + return err + } else if !fipsApproved { + fips140.RecordNonApproved() + } + + if len(sig) != pub.Size() { + return ErrVerification + } + + emBits := pub.N.BitLen() - 1 + emLen := (emBits + 7) / 8 + em, err := encrypt(pub, sig) + if err != nil { + return ErrVerification + } + + // Like in signPSSWithSalt, deal with mismatches between emLen and the size + // of the modulus. The spec would have us wire emLen into the encoding + // function, but we'd rather always encode to the size of the modulus and + // then strip leading zeroes if necessary. This only happens for weird + // modulus sizes anyway. + for len(em) > emLen && len(em) > 0 { + if em[0] != 0 { + return ErrVerification + } + em = em[1:] + } + + return emsaPSSVerify(digest, em, emBits, saltLength, hash) +} + +func checkApprovedHash(hash hash.Hash) { + switch hash.(type) { + case *sha256.Digest, *sha512.Digest, *sha3.Digest: + default: + fips140.RecordNonApproved() + } +} + +// EncryptOAEP encrypts the given message with RSAES-OAEP. +func EncryptOAEP(hash, mgfHash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) { + // Note that while we don't commit to deterministic execution with respect + // to the random stream, we also don't apply MaybeReadByte, so per Hyrum's + // Law it's probably relied upon by some. It's a tolerable promise because a + // well-specified number of random bytes is included in the ciphertext, in a + // well-specified way. + + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHash(hash) + if fipsApproved, err := checkPublicKey(pub); err != nil { + return nil, err + } else if !fipsApproved { + fips140.RecordNonApproved() + } + k := pub.Size() + if len(msg) > k-2*hash.Size()-2 { + return nil, ErrMessageTooLong + } + + hash.Reset() + hash.Write(label) + lHash := hash.Sum(nil) + + em := make([]byte, k) + seed := em[1 : 1+hash.Size()] + db := em[1+hash.Size():] + + copy(db[0:hash.Size()], lHash) + db[len(db)-len(msg)-1] = 1 + copy(db[len(db)-len(msg):], msg) + + if err := drbg.ReadWithReaderDeterministic(random, seed); err != nil { + return nil, err + } + + mgf1XOR(db, mgfHash, seed) + mgf1XOR(seed, mgfHash, db) + + return encrypt(pub, em) +} + +// DecryptOAEP decrypts ciphertext using RSAES-OAEP. +func DecryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { + fipsSelfTest() + fips140.RecordApproved() + checkApprovedHash(hash) + + k := priv.pub.Size() + if len(ciphertext) > k || + k < hash.Size()*2+2 { + return nil, ErrDecryption + } + + em, err := decrypt(priv, ciphertext, noCheck) + if err != nil { + return nil, err + } + + hash.Reset() + hash.Write(label) + lHash := hash.Sum(nil) + + firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) + + seed := em[1 : hash.Size()+1] + db := em[hash.Size()+1:] + + mgf1XOR(seed, mgfHash, db) + mgf1XOR(db, mgfHash, seed) + + lHash2 := db[0:hash.Size()] + + // We have to validate the plaintext in constant time in order to avoid + // attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal + // Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1 + // v2.0. In J. Kilian, editor, Advances in Cryptology. + lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2) + + // The remainder of the plaintext must be zero or more 0x00, followed + // by 0x01, followed by the message. + // lookingForIndex: 1 iff we are still looking for the 0x01 + // index: the offset of the first 0x01 byte + // invalid: 1 iff we saw a non-zero byte before the 0x01. + var lookingForIndex, index, invalid int + lookingForIndex = 1 + rest := db[hash.Size():] + + for i := 0; i < len(rest); i++ { + equals0 := subtle.ConstantTimeByteEq(rest[i], 0) + equals1 := subtle.ConstantTimeByteEq(rest[i], 1) + index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex) + invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid) + } + + if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 { + return nil, ErrDecryption + } + + return rest[index+1:], nil +} diff --git a/crypto/internal/fips140/rsa/pkcs1v22_test.go b/crypto/internal/fips140/rsa/pkcs1v22_test.go new file mode 100644 index 00000000000..fc607c8b358 --- /dev/null +++ b/crypto/internal/fips140/rsa/pkcs1v22_test.go @@ -0,0 +1,65 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "testing" + + "github.com/runZeroInc/excrypto/crypto/sha1" +) + +func TestEMSAPSS(t *testing.T) { + // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + msg := []byte{ + 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b, + 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb, + 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2, + 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c, + 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5, + 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02, + 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c, + 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0, + 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f, + 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c, + 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba, + 0x15, 0x98, 0x90, 0xfc, + } + salt := []byte{ + 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b, + 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61, + } + expected := []byte{ + 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24, + 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2, + 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e, + 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9, + 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f, + 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c, + 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1, + 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec, + 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3, + 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb, + 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89, + 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4, + 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc, + } + + hash := sha1.New() + hash.Write(msg) + hashed := hash.Sum(nil) + + encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New()) + if err != nil { + t.Errorf("Error from emsaPSSEncode: %s\n", err) + } + if !bytes.Equal(encoded, expected) { + t.Errorf("Bad encoding. got %x, want %x", encoded, expected) + } + + if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { + t.Errorf("Bad verification: %s", err) + } +} diff --git a/crypto/internal/fips140/rsa/rsa.go b/crypto/internal/fips140/rsa/rsa.go new file mode 100644 index 00000000000..83b3b8453f3 --- /dev/null +++ b/crypto/internal/fips140/rsa/rsa.go @@ -0,0 +1,460 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" +) + +type PublicKey struct { + N *bigmod.Modulus + E int +} + +// Size returns the modulus size in bytes. Raw signatures and ciphertexts +// for or by this public key will have the same size. +func (pub *PublicKey) Size() int { + return (pub.N.BitLen() + 7) / 8 +} + +type PrivateKey struct { + // pub has already been checked with checkPublicKey. + pub PublicKey + d *bigmod.Nat + // The following values are not set for deprecated multi-prime keys. + // + // Since they are always set for keys in FIPS mode, for SP 800-56B Rev. 2 + // purposes we always use the Chinese Remainder Theorem (CRT) format. + p, q *bigmod.Modulus // p × q = n + // dP and dQ are used as exponents, so we store them as big-endian byte + // slices to be passed to [bigmod.Nat.Exp]. + dP []byte // d mod (p - 1) + dQ []byte // d mod (q - 1) + qInv *bigmod.Nat // qInv = q⁻¹ mod p + // fipsApproved is false if this key does not comply with FIPS 186-5 or + // SP 800-56B Rev. 2. + fipsApproved bool +} + +func (priv *PrivateKey) PublicKey() *PublicKey { + return &priv.pub +} + +// NewPrivateKey creates a new RSA private key from the given parameters. +// +// All values are in big-endian byte slice format, and may have leading zeros +// or be shorter if leading zeroes were trimmed. +func NewPrivateKey(N []byte, e int, d, P, Q []byte) (*PrivateKey, error) { + n, err := bigmod.NewModulus(N) + if err != nil { + return nil, err + } + p, err := bigmod.NewModulus(P) + if err != nil { + return nil, err + } + q, err := bigmod.NewModulus(Q) + if err != nil { + return nil, err + } + dN, err := bigmod.NewNat().SetBytes(d, n) + if err != nil { + return nil, err + } + return newPrivateKey(n, e, dN, p, q) +} + +func newPrivateKey(n *bigmod.Modulus, e int, d *bigmod.Nat, p, q *bigmod.Modulus) (*PrivateKey, error) { + pMinusOne := p.Nat().SubOne(p) + pMinusOneMod, err := bigmod.NewModulus(pMinusOne.Bytes(p)) + if err != nil { + return nil, err + } + dP := bigmod.NewNat().Mod(d, pMinusOneMod).Bytes(pMinusOneMod) + + qMinusOne := q.Nat().SubOne(q) + qMinusOneMod, err := bigmod.NewModulus(qMinusOne.Bytes(q)) + if err != nil { + return nil, err + } + dQ := bigmod.NewNat().Mod(d, qMinusOneMod).Bytes(qMinusOneMod) + + // Constant-time modular inversion with prime modulus by Fermat's Little + // Theorem: qInv = q⁻¹ mod p = q^(p-2) mod p. + if p.Nat().IsOdd() == 0 { + // [bigmod.Nat.Exp] requires an odd modulus. + return nil, errors.New("crypto/rsa: p is even") + } + pMinusTwo := p.Nat().SubOne(p).SubOne(p).Bytes(p) + qInv := bigmod.NewNat().Mod(q.Nat(), p) + qInv.Exp(qInv, pMinusTwo, p) + + pk := &PrivateKey{ + pub: PublicKey{ + N: n, E: e, + }, + d: d, p: p, q: q, + dP: dP, dQ: dQ, qInv: qInv, + } + if err := checkPrivateKey(pk); err != nil { + return nil, err + } + return pk, nil +} + +// NewPrivateKeyWithPrecomputation creates a new RSA private key from the given +// parameters, which include precomputed CRT values. +func NewPrivateKeyWithPrecomputation(N []byte, e int, d, P, Q, dP, dQ, qInv []byte) (*PrivateKey, error) { + n, err := bigmod.NewModulus(N) + if err != nil { + return nil, err + } + p, err := bigmod.NewModulus(P) + if err != nil { + return nil, err + } + q, err := bigmod.NewModulus(Q) + if err != nil { + return nil, err + } + dN, err := bigmod.NewNat().SetBytes(d, n) + if err != nil { + return nil, err + } + qInvNat, err := bigmod.NewNat().SetBytes(qInv, p) + if err != nil { + return nil, err + } + + pk := &PrivateKey{ + pub: PublicKey{ + N: n, E: e, + }, + d: dN, p: p, q: q, + dP: dP, dQ: dQ, qInv: qInvNat, + } + if err := checkPrivateKey(pk); err != nil { + return nil, err + } + return pk, nil +} + +// NewPrivateKeyWithoutCRT creates a new RSA private key from the given parameters. +// +// This is meant for deprecated multi-prime keys, and is not FIPS 140 compliant. +func NewPrivateKeyWithoutCRT(N []byte, e int, d []byte) (*PrivateKey, error) { + n, err := bigmod.NewModulus(N) + if err != nil { + return nil, err + } + dN, err := bigmod.NewNat().SetBytes(d, n) + if err != nil { + return nil, err + } + pk := &PrivateKey{ + pub: PublicKey{ + N: n, E: e, + }, + d: dN, + } + if err := checkPrivateKey(pk); err != nil { + return nil, err + } + return pk, nil +} + +// Export returns the key parameters in big-endian byte slice format. +// +// P, Q, dP, dQ, and qInv may be nil if the key was created with +// NewPrivateKeyWithoutCRT. +func (priv *PrivateKey) Export() (N []byte, e int, d, P, Q, dP, dQ, qInv []byte) { + N = priv.pub.N.Nat().Bytes(priv.pub.N) + e = priv.pub.E + d = priv.d.Bytes(priv.pub.N) + if priv.dP == nil { + return + } + P = priv.p.Nat().Bytes(priv.p) + Q = priv.q.Nat().Bytes(priv.q) + dP = bytes.Clone(priv.dP) + dQ = bytes.Clone(priv.dQ) + qInv = priv.qInv.Bytes(priv.p) + return +} + +// checkPrivateKey is called by the NewPrivateKey and GenerateKey functions, and +// is allowed to modify priv.fipsApproved. +func checkPrivateKey(priv *PrivateKey) error { + priv.fipsApproved = true + + if fipsApproved, err := checkPublicKey(&priv.pub); err != nil { + return err + } else if !fipsApproved { + priv.fipsApproved = false + } + + if priv.dP == nil { + // Legacy and deprecated multi-prime keys. + priv.fipsApproved = false + return nil + } + + N := priv.pub.N + p := priv.p + q := priv.q + + // FIPS 186-5, Section 5.1 requires "that p and q be of the same bit length." + if p.BitLen() != q.BitLen() { + priv.fipsApproved = false + } + + // Check that pq ≡ 1 mod N (and that p < N and q < N). + pN := bigmod.NewNat().ExpandFor(N) + if _, err := pN.SetBytes(p.Nat().Bytes(p), N); err != nil { + return errors.New("crypto/rsa: invalid prime") + } + qN := bigmod.NewNat().ExpandFor(N) + if _, err := qN.SetBytes(q.Nat().Bytes(q), N); err != nil { + return errors.New("crypto/rsa: invalid prime") + } + if pN.Mul(qN, N).IsZero() != 1 { + return errors.New("crypto/rsa: p * q != n") + } + + // Check that de ≡ 1 mod p-1, and de ≡ 1 mod q-1. + // + // This implies that e is coprime to each p-1 as e has a multiplicative + // inverse. Therefore e is coprime to lcm(p-1,q-1) = λ(N). + // It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 mod p. Thus a^de ≡ a + // mod n for all a coprime to n, as required. + // + // This checks dP, dQ, and e. We don't check d because it is not actually + // used in the RSA private key operation. + pMinus1, err := bigmod.NewModulus(p.Nat().SubOne(p).Bytes(p)) + if err != nil { + return errors.New("crypto/rsa: invalid prime") + } + dP, err := bigmod.NewNat().SetBytes(priv.dP, pMinus1) + if err != nil { + return errors.New("crypto/rsa: invalid CRT exponent") + } + de := bigmod.NewNat() + de.SetUint(uint(priv.pub.E)).ExpandFor(pMinus1) + de.Mul(dP, pMinus1) + if de.IsOne() != 1 { + return errors.New("crypto/rsa: invalid CRT exponent") + } + + qMinus1, err := bigmod.NewModulus(q.Nat().SubOne(q).Bytes(q)) + if err != nil { + return errors.New("crypto/rsa: invalid prime") + } + dQ, err := bigmod.NewNat().SetBytes(priv.dQ, qMinus1) + if err != nil { + return errors.New("crypto/rsa: invalid CRT exponent") + } + de.SetUint(uint(priv.pub.E)).ExpandFor(qMinus1) + de.Mul(dQ, qMinus1) + if de.IsOne() != 1 { + return errors.New("crypto/rsa: invalid CRT exponent") + } + + // Check that qInv * q ≡ 1 mod p. + qP, err := bigmod.NewNat().SetOverflowingBytes(q.Nat().Bytes(q), p) + if err != nil { + // q >= 2^⌈log2(p)⌉ + qP = bigmod.NewNat().Mod(q.Nat(), p) + } + if qP.Mul(priv.qInv, p).IsOne() != 1 { + return errors.New("crypto/rsa: invalid CRT coefficient") + } + + // Check that |p - q| > 2^(nlen/2 - 100). + // + // If p and q are very close to each other, then N=pq can be trivially + // factored using Fermat's factorization method. Broken RSA implementations + // do generate such keys. See Hanno Böck, Fermat Factorization in the Wild, + // https://eprint.iacr.org/2023/026.pdf. + diff := bigmod.NewNat() + if qP, err := bigmod.NewNat().SetBytes(q.Nat().Bytes(q), p); err != nil { + // q > p + pQ, err := bigmod.NewNat().SetBytes(p.Nat().Bytes(p), q) + if err != nil { + return errors.New("crypto/rsa: p == q") + } + // diff = 0 - p mod q = q - p + diff.ExpandFor(q).Sub(pQ, q) + } else { + // p > q + // diff = 0 - q mod p = p - q + diff.ExpandFor(p).Sub(qP, p) + } + // A tiny bit of leakage is acceptable because it's not adaptive, an + // attacker only learns the magnitude of p - q. + if diff.BitLenVarTime() <= N.BitLen()/2-100 { + return errors.New("crypto/rsa: |p - q| too small") + } + + // Check that d > 2^(nlen/2). + // + // See section 3 of https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf + // for more details about attacks on small d values. + // + // Likewise, the leakage of the magnitude of d is not adaptive. + if priv.d.BitLenVarTime() <= N.BitLen()/2 { + return errors.New("crypto/rsa: d too small") + } + + // If the key is still in scope for FIPS mode, perform a Pairwise + // Consistency Test. + if priv.fipsApproved { + if err := fips140.PCT("RSA sign and verify PCT", func() error { + hash := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + sig, err := signPKCS1v15(priv, "SHA-256", hash) + if err != nil { + return err + } + return verifyPKCS1v15(priv.PublicKey(), "SHA-256", hash, sig) + }); err != nil { + return err + } + } + + return nil +} + +func checkPublicKey(pub *PublicKey) (fipsApproved bool, err error) { + fipsApproved = true + if pub.N == nil { + return false, errors.New("crypto/rsa: missing public modulus") + } + if pub.N.Nat().IsOdd() == 0 { + return false, errors.New("crypto/rsa: public modulus is even") + } + // FIPS 186-5, Section 5.1: "This standard specifies the use of a modulus + // whose bit length is an even integer and greater than or equal to 2048 + // bits." + if pub.N.BitLen() < 2048 { + fipsApproved = false + } + if pub.N.BitLen()%2 == 1 { + fipsApproved = false + } + if pub.E < 2 { + return false, errors.New("crypto/rsa: public exponent too small or negative") + } + // e needs to be coprime with p-1 and q-1, since it must be invertible + // modulo λ(pq). Since p and q are prime, this means e needs to be odd. + if pub.E&1 == 0 { + return false, errors.New("crypto/rsa: public exponent is even") + } + // FIPS 186-5, Section 5.5(e): "The exponent e shall be an odd, positive + // integer such that 2¹⁶ < e < 2²⁵⁶." + if pub.E <= 1<<16 { + fipsApproved = false + } + // We require pub.E to fit into a 32-bit integer so that we + // do not have different behavior depending on whether + // int is 32 or 64 bits. See also + // https://www.imperialviolet.org/2012/03/16/rsae.html. + if pub.E > 1<<31-1 { + return false, errors.New("crypto/rsa: public exponent too large") + } + return fipsApproved, nil +} + +// Encrypt performs the RSA public key operation. +func Encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) { + fips140.RecordNonApproved() + if _, err := checkPublicKey(pub); err != nil { + return nil, err + } + return encrypt(pub, plaintext) +} + +func encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) { + m, err := bigmod.NewNat().SetBytes(plaintext, pub.N) + if err != nil { + return nil, err + } + return bigmod.NewNat().ExpShortVarTime(m, uint(pub.E), pub.N).Bytes(pub.N), nil +} + +var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size") +var ErrDecryption = errors.New("crypto/rsa: decryption error") +var ErrVerification = errors.New("crypto/rsa: verification error") + +const withCheck = true +const noCheck = false + +// DecryptWithoutCheck performs the RSA private key operation. +func DecryptWithoutCheck(priv *PrivateKey, ciphertext []byte) ([]byte, error) { + fips140.RecordNonApproved() + return decrypt(priv, ciphertext, noCheck) +} + +// DecryptWithCheck performs the RSA private key operation and checks the +// result to defend against errors in the CRT computation. +func DecryptWithCheck(priv *PrivateKey, ciphertext []byte) ([]byte, error) { + fips140.RecordNonApproved() + return decrypt(priv, ciphertext, withCheck) +} + +// decrypt performs an RSA decryption of ciphertext into out. If check is true, +// m^e is calculated and compared with ciphertext, in order to defend against +// errors in the CRT computation. +func decrypt(priv *PrivateKey, ciphertext []byte, check bool) ([]byte, error) { + if !priv.fipsApproved { + fips140.RecordNonApproved() + } + + var m *bigmod.Nat + N, E := priv.pub.N, priv.pub.E + + c, err := bigmod.NewNat().SetBytes(ciphertext, N) + if err != nil { + return nil, ErrDecryption + } + + if priv.dP == nil { + // Legacy codepath for deprecated multi-prime keys. + fips140.RecordNonApproved() + m = bigmod.NewNat().Exp(c, priv.d.Bytes(N), N) + + } else { + P, Q := priv.p, priv.q + t0 := bigmod.NewNat() + // m = c ^ Dp mod p + m = bigmod.NewNat().Exp(t0.Mod(c, P), priv.dP, P) + // m2 = c ^ Dq mod q + m2 := bigmod.NewNat().Exp(t0.Mod(c, Q), priv.dQ, Q) + // m = m - m2 mod p + m.Sub(t0.Mod(m2, P), P) + // m = m * Qinv mod p + m.Mul(priv.qInv, P) + // m = m * q mod N + m.ExpandFor(N).Mul(t0.Mod(Q.Nat(), N), N) + // m = m + m2 mod N + m.Add(m2.ExpandFor(N), N) + } + + if check { + c1 := bigmod.NewNat().ExpShortVarTime(m, uint(E), N) + if c1.Equal(c) != 1 { + return nil, ErrDecryption + } + } + + return m.Bytes(N), nil +} diff --git a/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt b/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt new file mode 100644 index 00000000000..b5a0c17ed2a --- /dev/null +++ b/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt @@ -0,0 +1,279 @@ +# GCD tests. +# +# These test vectors satisfy gcd(A, B) = GCD and lcm(A, B) = LCM. + +GCD = 0 +A = 0 +B = 0 +# Just to appease the syntax-checker. +LCM = 0 + +GCD = 1 +A = 92ff140ac8a659b31dd904161f9213706a08a817ae845e522c3af0c9096699e059b47c8c2f16434b1c5766ebb384b79190f2b2a62c2378f45e116890e7bb407a +B = 2f532c9e5902b0d68cd2ed69b2083bc226e8b04c549212c425a5287bb171c6a47fcb926c70cc0d34b8d6201c617aee66af865d31fdc8a2eeb986c19da8bb0897 +LCM = 1b2c97003e520b0bdd59d8c35a180b4aa36bce14211590435b990ad8f4c034ce3c77899581cb4ee1a022874203459b6d53859ab1d99ff755efa253fc0e5d8487bb000c13c566e8937f0fe90b95b68bc278610d4f232770b08d1f31bee55a03da47f2d0ebb9e7861c4f16cc22168b68593e9efcde00f54104b4c3e1a0b294d7f6 + +GCD = a +A = faaffa431343074f5c5d6f5788500d7bc68b86eb37edf166f699b4d75b76dae2cb7c8f6eccae8f18f6d510ef72f0b9633d5740c0bebb934d3be796bd9a53808e +B = 2f48ec5aa5511283c2935b15725d30f62244185573203b48c7eb135b2e6db5c115c9446ac78b020574665b06a75eb287e0dbeb5da7c193294699b4c2129d2ac4 +LCM = 4a15f305e9622aa19bd8f39e968bfc16d527a47f7a5219d7b02c242c77ef8b608a4a6141f643ca97cedf07c0f1f3e8879d2568b056718aa15c0756899a08ccbe0a658bae67face96fa110edb91757bfa4828e8ff7c5d71b204f36238b12dd26f17be8ba9771f7068d63e41d423671f898f054b1187605754bc5546f2b02c5ac + +GCD = 16 +A = cf0b21bde98b41b479ac8071086687a6707e9efaacd4e5299668ce1be8b13290f27fd32ae68df87c292e8583a09d73ec8e8a04a65a487380dcd7dacca3b6e692 +B = 3be3f563f81d5ad5c1211db7eff430aa345e830ce07b4bde7d4d32dba3ac618d2034351e5435fd6c7f077971fb4a1e83a7396a74fdff7fce1267112851db2582 +LCM = 233a2188de2c017235024b182286f17562b2ee5ab9fdfe4efa2f61c4ff99fa44e1ead5bf6cde05bd7502ce78373c83e3f9dbab0c9bb8620a87c2640bce5d12c685af656df789bb3d0ba1edbaa98cf4f0166d422ab17aa6706f8132264d45b72827d6671a00a9186e723379e3a3bb7902d08865f357c74100059f83800241976 + +GCD = 1 +A = dd7b7597d7c1eb399b1cea9b3042c14bd6022d31b1d2642a8f82fc32de6eadaf012fbbf349eaec4922a8468740ca73c6090833d6a69a380ed947b39c2f9b0b76 +B = 8e0dc8654e70eec55496038a8d3fff3c2086bc6dbfc0e2dbdf5bd7de03c5aef01a3982556ac3fc34fd5f13368be6cdc252c82367b7462e210f940f847d382dd9 +LCM = 7ae667df4bd4dd35bbec28719a9f1b5e1f396a9ab386c086742a6ab3014a3386d39f35b50624d0c5b4e6b206c2635c7de5ea69e2faa85dd616a7e36622962a07632839857aa49332942feccff2aee1c962e2f4e8ccfd738a5da5bf528b4c5a2440409350f5a17a39d234403e8482ccf838e0d2758ccfb8018198a51dbb407506 + +GCD = 1 +A = 0 +B = 1 +LCM = 0 + +GCD = 1 +A = 1 +B = 0 +LCM = 0 + +GCD = 1 +A = 1 +B = 1 +LCM = 1 + +GCD = 2b2 +A = dfccaa3549c1b59ab3e114fe87dc5d187719abad58c51724e972741eb895ab79a49f385f61d531ec5c88dbb505ae375093fa848165f71a5ed65e7832a42ade191a +B = fa58a81f43088da45e659fc1117d0f1cd015aa096c8e5377cf1832191baf7cc28b5c24998b93b64f8900a0973faedb9babaaf1854345f011739da8f1175d9684c +LCM = 5132f7ab7a982b9dc55114bd96800b7637f9742cf8a7a00a0d69d5e4574fc85792c89a1c52bcfc74b9d7f3f6164819466c46b2d622e280ced7ad1211604084a15dc1fd1951a05c8ce37122c0ec15891d818a70d3763670ea3195098de9b1ca50ea89893a9753fb9ea801541058f44801f7f50967124abfc864a2b01c41f94193c + +GCD = 8e +A = 248d96a8a4cab0a1b194e08c1146868b094597cadbc35531f0ed2d77cba9f15cb5cc7c10e64ce054bf93396d25259d750b3de3aba65073db1fd2b852a6454ac1a +B = 4c7bad8e1844901fd6a2ce2edc82e698d28ec95d6672ca148d85b49ecc78dd0a8b870e202244210bc98592b99ff6abbd20630f9eee7d46b15ccfae8d08b86799de +LCM = 13b01f9d9c6c13e90c97e3d95bbce5a835c631b3de3bd4ff5df13ad850f5223dbdf71c53912275d0397df9335ef3a3ba8e4684c6b25962bb7b18bc74144cb5edf0196f79863a7ff032619a71646a92281f7baace7f223d254cb4d05ec19bf8d4c8ce4455a9d770daec89c0d3cf338cbdae39cf982b3c4568f5c9def4e1133d28a + +GCD = 3e55 +A = 2fa97382f46676b7a4cc2b8153f17b58792d24660e187d33ce55c81cc193ccb6e1e2b89feea1d5fd8faa36e13bf947fb48635e450a4d1488d0978324194a1f43c6 +B = ab08ad074139963bc18e5d87ba68db64ca6f4c279616c64039b02c55f2375b3bc04114e8e05e1ba92fb6470768f61d123845aea36774c18612736a220934561faf +LCM = 82c7c377ecda2cb9228604cd287df5eff94edd4a539c3eb3b3fdd4b4a79d2f4eaf2b22f8286272d3dad2e370cfcd9ea4d93ebb3f049c52b8fa23b68a5bf79af989822e2cfb978f68c6a5058f47319dffcb455b089b06ae6db9e5c8a2b6e951d6e118bd2b4cd08b6e5733476a446a57387d940d1289ec00e24315821ed3a5daf2 + +GCD = a7a +A = 923706dfed67834a1e7e6c8e8e9f93bfbc0b43ca1f324886cf1f1380fb9b77109275d4b50af1b7689802fe9b3623ac46c7ba0e17e908c20278127b07a5c12d86ec +B = 64473e878a29021fac1c1ce34a63eae1f4f83ee6851333b67213278b9a4a16f005cba0e8cdb410035bb580062f0e486c1a3a01f4a4edf782495f1dc3ebfa837d86 +LCM = 57785ca45b8873032f1709331436995525eed815c55140582ce57fd852116835deac7ca9d95ce9f280e246ea4d4f1b7140ab7e0dd6dc869de87f1b27372098b155ad0a1828fd387dff514acc92eae708609285edaab900583a786caf95153f71e6e6092c8c5ee727346567e6f58d60a5e01c2fa8ebcf86da9ea46876ecc58e914 + +GCD = 42 +A = 0 +B = 42 +LCM = 0 + +GCD = 42 +A = 42 +B = 0 +LCM = 0 + +GCD = 42 +A = 42 +B = 42 +LCM = 42 + +GCD = f60d +A = ef7886c3391407529d5cf2e75ed53e5c3f74439ad2e2dc48a79bc1a5322789b4ced2914b97f8ff4b9910d212243b54001eb8b375365b9a87bd022dd3772c78a9fd63 +B = d1d3ec32fa3103911830d4ec9f629c5f75af7039e307e05bc2977d01446cd2cbeeb8a8435b2170cf4d9197d83948c7b8999d901fe47d3ce7e4d30dc1b2de8af0c6e4 +LCM = cc376ed2dc362c38a45a719b2ed48201dab3e5506e3f1314e57af229dc7f3a6a0dad3d21cfb148c23a0bbb0092d667051aa0b35cff5b5cc61a7c52dec4ed72f6783edf181b3bf0500b79f87bb95abc66e4055f259791e4e5eb897d82de0e128ecf8a091119475351d65b7f320272db190898a02d33f45f03e27c36cb1c45208037dc + +GCD = 9370 +A = 1ee02fb1c02100d1937f9749f628c65384ff822e638fdb0f42e27b10ee36e380564d6e861fcad0518f4da0f8636c1b9f5124c0bc2beb3ca891004a14cd7b118ddfe0 +B = 67432fd1482d19c4a1c2a4997eab5dbf9c5421977d1de60b739af94c41a5ad384cd339ebfaa43e5ad6441d5b9aaed5a9f7485025f4b4d5014e1e406d5bd838a44e50 +LCM = 159ff177bdb0ffbd09e2aa7d86de266c5de910c12a48cbe61f6fa446f63a2151194777555cd59903d24cb30965973571fb1f89c26f2b760526f73ded7ee8a34ebcecd1a3374a7559bcdb9ac6e78be17a62b830d6bb3982afdf10cf83d61fd0d588eab17d6abef8e6a7a5763fcb766d9a4d86adf5bb904f2dd6b528b9faec603987a0 + +GCD = c5f +A = 5a3a2088b5c759420ed0fb9c4c7685da3725b659c132a710ef01e79435e63d009d2931ea0a9ed9432f3d6b8851730c323efb9db686486614332c6e6ba54d597cf98 +B = 1b1eb33b006a98178bb35bbcf09c5bebd92d9ace79fa34c1567efa8d6cf6361547807cd3f8e7b8cd3ddb6209dccbae4b4c16c8c1ec19741a3a57f61571882b7aed7 +LCM = c5cbbbe9532d30d2a7dd7c1c8a6e69fd4fa4828a844d6afb44f3747fef584f7f1f3b835b006f8747d84f7699e88f6267b634e7aef78d6c7584829537d79514eec7d11219721f91015f5cefdc296261d85dba388729438991a8027de4827cd9eb575622e2912b28c9ce26d441e97880d18db025812cef5de01adeaec1322a9c9858 + +GCD = e052 +A = 67429f79b2ec3847cfc7e662880ab1d94acdf04284260fcfffd67c2862d59704ed45bcc53700c88a5eea023bc09029e9fd114fc94c227fd47a1faa1a5ef117b09bd2 +B = 39faa7cbdeb78f9028c1d50ab34fbe6924c83a1262596f6b85865d4e19cc258b3c3af1ee2898e39e5bee5839e92eac6753bbbb0253bd576d1839a59748b778846a86 +LCM = 1ab071fb733ef142e94def10b26d69982128561669e58b20b80d39cf7c2759d26b4a65d73b7f940c6e8fc417180ef62d7e52ac24678137bd927cd8d004ad52b02affe176a1ecde903dbc26dcc705678f76dd8cd874c0c3fe737474309767507bbe70dd7fb671bbb3694cedf0dcdaa0c716250ddd6dfec525261572fa3e1387f7b906 + +GCD = 3523 +A = 0 +B = 3523 +LCM = 0 + +GCD = 3523 +A = 3523 +B = 0 +LCM = 0 + +GCD = 3523 +A = 3523 +B = 3523 +LCM = 3523 + +GCD = f035a941 +A = 16cd5745464dfc426726359312398f3c4486ed8aaeea6386a67598b10f744f336c89cdafcb18e643d55c3a62f4ab2c658a0d19ea3967ea1af3aee22e11f12c6df6e886f7 +B = 74df09f309541d26b4b39e0c01152b8ad05ad2dfe9dd2b6706240e9d9f0c530bfb9e4b1cad3d4a94342aab309e66dd42d9df01b47a45173b507e41826f24eb1e8bcc4459 +LCM = b181771d0e9d6b36fdfcbf01d349c7de6b7e305e1485ea2aa32938aa919a3eee9811e1c3c649068a7572f5d251b424308da31400d81ac4078463f9f71d7efd2e681f92b13a6ab3ca5c9063032dcbdf3d3a9940ce65e54786463bbc06544e1280f25bc7579d264f6f1590cf09d1badbf542ce435a14ab04d25d88ddbac7d22e8cae1c91f + +GCD = 33ad1b8f +A = 1af010429a74e1b612c2fc4d7127436f2a5dafda99015ad15385783bd3af8d81798a57d85038bcf09a2a9e99df713b4d6fc1e3926910fbbf1f006133cb27dc5ebb9cca85 +B = 92a4f45a90965a4ef454f1cdd883d20f0f3be34d43588b5914677c39d577a052d1b25a522be1a656860a540970f99cbc8a3adf3e2139770f664b4b7b9379e13daf7d26c +LCM = 4c715520ed920718c3b2f62821bc75e3ff9fd184f76c60faf2906ef68d28cd540d3d6c071fa8704edd519709c3b09dfaee12cb02ab01ad0f3af4f5923d5705ce6d18bcab705a97e21896bb5dd8acb36ee8ec98c254a4ddc744297827a33c241f09016a5f109248c83dd41e4cea73ce3eabb28d76678b7e15545b96d22da83c111b6b624 + +GCD = dc0429aa +A = ccb423cfb78d7150201a97114b6644e8e0bbbb33cadb0ef5da5d3c521a244ec96e6d1538c64c10c85b2089bdd702d74c505adce9235aa4195068c9077217c0d431de7f96 +B = 710786f3d9022fc3acbf47ac901f62debcfda684a39234644bac630ab2d211111df71c0844b02c969fc5b4c5a15b785c96efd1e403514235dc9356f7faf75a0888de5e5a +LCM = 6929af911850c55450e2f2c4c9a72adf284fe271cf26e41c66e1a2ee19e30d928ae824f13d4e2a6d7bb12d10411573e04011725d3b6089c28d87738749107d990162b485805f5eedc8f788345bcbb5963641f73c303b2d92f80529902d3c2d7899623958499c8a9133aae49a616c96a2c5482a37947f23af18c3247203ac2d0e760340e6 + +GCD = 743166058 +A = 16cd476e8031d4624716238a3f85badd97f274cdfd9d53e0bd74de2a6c46d1827cc83057f3889588b6b7ca0640e7d743ed4a6eaf6f9b8df130011ecc72f56ef0af79680 +B = 86eba1fc8d761f22e0f596a03fcb6fe53ad15a03f5b4e37999f60b20966f78ba3280f02d3853f9ace40438ccfaf8faed7ace2f2bf089b2cdd4713f3f293bf602666c39f8 +LCM = 1a7a1b38727324d6ba0290f259b8e2b89c339b2445cada38a5a00ded1468ab069f40678ce76f7f78c7c6f97783cc8a49ef7e2a0c73abbac3abc66d1ce99566ce7f874a8949ca3442051e71967695dc65361184748c1908e1b587dc02ed899a524b34eb30b6f8db302432cfa1a8fbf2c46591e0ab3db7fd32c01b1f86c39832ee9f0c80 + +GCD = 6612ba2c +A = 0 +B = 6612ba2c +LCM = 0 + +GCD = 6612ba2c +A = 6612ba2c +B = 0 +LCM = 0 + +GCD = 6612ba2c +A = 6612ba2c +B = 6612ba2c +LCM = 6612ba2c + +GCD = 2272525aa08ccb20 +A = 11b9e23001e7446f6483fc9977140d91c3d82568dabb1f043a5620544fc3dda233b51009274cdb004fdff3f5c4267d34181d543d913553b6bdb11ce2a9392365fec8f9a3797e1200 +B = 11295529342bfb795f0611d03afb873c70bd16322b2cf9483f357f723b5b19f796a6206cf3ae3982daaeafcd9a68f0ce3355a7eba3fe4e743683709a2dd4b2ff46158bd99ff4d5a0 +LCM = 8d4cbf00d02f6adbaa70484bcd42ea932000843dcb667c69b75142426255f79b6c3b6bf22572597100c06c3277e40bf60c14c1f4a6822d86167812038cf1eefec2b0b19981ad99ad3125ff4a455a4a8344cbc609e1b3a173533db432bd717c72be25e05ed488d3970e7ed17a46353c5e0d91c8428d2fec7a93210759589df042cab028f545e3a00 + +GCD = 3480bf145713d56f9 +A = 8cf8ef1d4f216c6bcec673208fd93b7561b0eb8303af57113edc5c6ff4e1eeae9ddc3112b943d947653ba2179b7f63505465126d88ad0a0a15b682f5c89aa4a2a51c768cd9fdeaa9 +B = a6fd114023e7d79017c552a9051ca827f3ffa9f31e2ee9d78f8408967064fcdc9466e95cc8fac9a4fa88248987caf7cf57af58400d27abd60d9b79d2fe03fad76b879eceb504d7f +LCM = 1c05eee73a4f0db210a9007f94a5af88c1cdd2cba456061fd41de1e746d836fa4e0e972812842e0f44f10a61505f5d55760c48ba0d06af78bb6bde7da8b0080b29f82b1161e9c0b5458e05ac090b00f4d78b1cc10cf065124ba610e3acab092a36fe408525e21c0ddc7c9696ed4e48bd2f70423deecfe62cecc865c6088f265da0e5961d3f3a84f + +GCD = 917e74ae941fcaae +A = 652f8a92d96cbf0a309629011d0fbaceb1266bc2e8243d9e494eead4cf7100c661b537a8bea93dec88cfc68597d88a976c125c3b4de19aba38d4ea9578202e59848d42652518348a +B = 32e07b71979d57e8344e97c39680a61e07d692d824ae26b682156890792d8a766ee29a4968f461aaced5bf049044fba2f4120b1c1f05985676f975d4582e9e82750d73c532cd07b2 +LCM = 23620c7b897dc26c7717e32f3517ac70bf09fbe08f7255ab010cf4cf946f4e96304c425043452c5d5a0e841d3a3cfd9c2d84d9256f3b5974fe3ebfa9255fe20a710d3e6511606c0d85970381101c7f4986d65ad6a73a71507f146b11f903043cfa805cc0b14d4f3072da98bf22282f7762040406c02d5b3ef9e7587f63bab8b29c61d8e30911aa96 + +GCD = 2b9adc82005b2697 +A = 19764a84f46045ef1bca571d3cbf49b4545998e64d2e564cc343a53bc7a0bcfbe0baa5383f2b346e224eb9ce1137d9a4f79e8e19f946a493ff08c9b423574d56cbe053155177c37 +B = 1bbd489ad2ab825885cdac571a95ab4924e7446ce06c0f77cf29666a1e20ed5d9bc65e4102e11131d824acad1592075e13024e11f12f8210d86ab52aa60deb250b3930aabd960e5a +LCM = 1032a0c5fffc0425e6478185db0e5985c645dd929c7ebfeb5c1ee12ee3d7b842cfab8c9aa7ff3131ac41d4988fb928c0073103cea6bb2cc39808f1b0ad79a6d080eac5a0fc6e3853d43f903729549e03dba0a4405500e0096b9c8e00510c1852982baec441ed94efb80a78ed28ed526d055ad34751b831b8749b7c19728bf229357cc5e17eb8e1a + +GCD = 8d9d4f30773c4edf +A = 0 +B = 8d9d4f30773c4edf +LCM = 0 + +GCD = 8d9d4f30773c4edf +A = 8d9d4f30773c4edf +B = 0 +LCM = 0 + +GCD = 8d9d4f30773c4edf +A = 8d9d4f30773c4edf +B = 8d9d4f30773c4edf +LCM = 8d9d4f30773c4edf + +GCD = 6ebd8eafb9a957a6c3d3d5016be604f9624b0debf04d19cdabccf3612bbd59e00 +A = 34dc66a0ffd5b8b5e0ffc858dfc4655753e59247c4f82a4d2543b1f7bb7be0e24d2bbf27bb0b2b7e56ee22b29bbde7baf0d7bfb96331e27ba029de9ffdff7bdb7dc4da836d0e58a0829367ec84ea256833fd4fe1456ad4dd920557a345e12000 +B = 1f3406a20e20ebf96ccb765f898889a19b7636608fd7dc7c212607b641399543f71111d60e42989de01eaa6ff19a86ea8fbde1a3d368c0d86dc899e8e250fc764090f337958ca493119cbb4ad70cbfae7097d06d4f90ec62fbdd3f0a4496e600 +LCM = ee502c50e3667946e9089d0a9a0382e7fd0b75a17db23b56a0eec997a112c4dbd56d188808f76fe90451e5605550c9559ef14a95014c6eb97e9c1c659b98515c41470142843de60f72fb4c235faa55b0a97d943221003d44e2c28928f0b84bf071256254897ed31a7fd8d174fc962bc1311f67900ac3abcad83a28e259812f1ee229511ab1d82d41f5add34693ba7519babd52eb4ec9de31581f5f2e40a000 + +GCD = ef7399b217fc6a62b90461e58a44b22e5280d480b148ec4e3b4d106583f8e428 +A = 7025e2fe5f00aec73d90f5ad80d99ca873f71997d58e59937423a5e6ddeb5e1925ed2fd2c36a5a9fc560c9023d6332c5d8a4b333d3315ed419d60b2f98ccf28bbf5bf539284fd070d2690aeaac747a3d6384ee6450903a64c3017de33c969c98 +B = df0ac41dbabce1deeb0bceb1b65b1079850052ecf6534d0cff84a5a7fb5e63baee028d240f4419925154b96eaa69e8fbb1aae5102db7916234f290aa60c5d7e69406f02aeea9fe9384afbff7d878c9ac87cd31f7c35dff243b1441e09baff478 +LCM = 687669343f5208a6b2bb2e2efcac41ec467a438fde288cc5ef7157d130139ba65db9eb53e86a30c870bd769c0e0ab15a50f656cd9626621ae68d85eaff491b98da3ea5812062e4145af11ea5e1da457084911961ef2cd2ac45715f885ba94b4082aa76ffd1f32461f47c845b229d350bf36514c5ce3a7c782418746be342eca2721346ade73a59475f178c4f2448e1326110f5d26a0fef1a7a0c9288489e4dc8 + +GCD = 84b917557acf24dff70cb282a07fc52548b6fbbe96ca8c46d0397c8e44d30573 +A = 81dbb771713342b33912b03f08649fb2506874b96125a1ac712bc94bfd09b679db7327a824f0a5837046f58af3a8365c89e06ff4d48784f60086a99816e0065a5f6f0f49066b0ff4c972a6b837b63373ca4bb04dcc21e5effb6dfe38271cb0fa +B = 1da91553c0a2217442f1c502a437bb14d8c385aa595db47b23a97b53927b4493dd19f1bc8baf145bc10052394243089a7b88d19b6f106e64a5ab34acad94538ab504d1c8ebf22ac42048bbd1d4b0294a2e12c09fe2a3bd92756ba7578cb34b39 +LCM = 1d0530f8142754d1ee0249b0c3968d0ae7570e37dadbe4824ab966d655abf04cd6de5eb700eba89d8352dec3ae51f2a10267c32fbd39b788c7c5047fe69da3d7ad505435a6212f44899ba7e983bb780f62bcdee6f94b7dba8af7070a4cc008f351ae8be4579bc4a2e5c659ce000ad9c8cdc83723b32c96aeb0f5f4127f6347353d05525f559a8543cd389ad0af6f9d08a75b8c0b32419c097e6efe8746aee92e + +GCD = 66091477ea3b37f115038095814605896e845b20259a772f09405a8818f644aa +A = cedac27069a68edfd49bd5a859173c8e318ba8be65673d9d2ba13c717568754ed9cbc10bb6c32da3b7238cff8c1352d6325668fd21b4e82620c2e75ee0c4b1aff6fb1e9b948bbdb1af83cecdf356299b50543b72f801b6a58444b176e4369e0 +B = 5f64ca1ba481f42c4c9cf1ffa0e515b52aa9d69ceb97c4a2897f2e9fa87f72bae56ee6c5227f354304994c6a5cc742d9f09b2c058521975f69ca5835bce898cf22b28457cd7e28870df14e663bb46c9be8f6662f4ff34d5c4ae17a888eba504e +LCM = c163cb28642e19a40aa77887c63180c2c49fc10cda98f6f929c8131752ea30b5283a814a81681b69b9d1762e6c1a9db85f480bc17f998d235fd7e64c1caa70ef170c9e816d3e80f516b29f2c80cfb68bf208b4d5082ef078da4314b3f20c7d6c54b0aeb378096b029a7b61c0a4cd14aeddc01004c53915a4f692d2291752e5af46b23d7fa6dd61f2d56c6f4bf8e6119688abac8fd7aba80e846a7764bb3fca0 + +GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +A = 0 +B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +LCM = 0 + +GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +B = 0 +LCM = 0 + +GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 +LCM = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 + +GCD = 120451d8307219aa0c96f328ad653ccd462e92423ca93ed8a3dde45bf5cb9b13cdaf9800e4d05dd71c4db6a129fb3280ee4ec96ec5297d881c1a8b5efccbd91fef21f5c5bf5fba42a4c8eaa358f620a074b7a17054527bdaa58d5acaa0dfdc48ecba1a10ebf4d57bb4215de406e6be13fed3fe493b1cd1e2d11a8d4ac03c47756 +A = 3f8179a8e1f0b342475a855c3e1bae402dd41424cf24a0b4d2e263c8efb08bde7d92eae8607fb5e88b1378f0f1bd0733f229a35be6b1383a48d32749d5d6b32427d26323b7ab05bb5781289e96bfbc21971439319b15f6c0fe93fdb35d0b67ec41443c59a081dd3cef047ac797fccb45bece84c0bb0bb7e1797259526d8ec9cc63ba4d32cfc692ccd3d243cb2b53ac216312f3a8e8c0daa09d21b6150d697639a5e52059414a417c607be8ec0eee2e708219cadbaf37a369c4485b01ed87bbc2 +B = 2c474e396a2dd9cd10b9d7313f69d3b4ca123e9fd853edd488339236d14c56453a1381958864a04d2624e81995dabcdd0ccf60db9917813f887de68da075d0ea4440001e18f470e43b38ee3440b49be651d709fbdef980e3e4149913f4ae2681124f54523f4881376ddb533b5219e804cc26f4c2e577be4e02613c4da80ba1215775b0a5178a965ad47bd2befb32493943ded1004ef66347b4983f8d1ba990d4a943505dfce6debcfb322842ed88106cd6dee9aa592ff0d2274bc727a6e1f14c +LCM = 9c129cf649555bfd2d3d9c64dc6d6f022295e53bca5d2f218adaa66aa60eb4694429b7e83bf81b6df4459c5104023ab9a33f006ffcd8114507baa17e2ef6fe23ebdd4740f66879033da2041f2cb7ba517ad3526ffe75614ea9432c085f71b2d65a736bac7ba42b639e330b82733372083843dcb78b6a273ab20e0d4b7c8998a14048aa15bb20a0a0bd997917107274c89b4cec175fb98043d52e6c555bd9e0036566d052a6d4e7e276d1e8835e1f06e3ca46d47747ba586e95fb1a790d992834b7c3e136141eb8a434e6c12067246ac3c0a81c69e03b1ed28aa0b3173d6eff83d278c2f461a47a416f3f9a5dae3bb410fd18817bd4115e7f1e84b936cc02364 + +GCD = 95aa569a2c76854300d7660847dd20fe0b8c445fdbcaa98465cee61aee76ad6a438e75a8c573198570ffb62bc07ec3a2be0ae0a1f631670fa88d6f75f3161e8b9a4d44b6801ffc884c7f469c5ed1f27b1edecce9f2977f9e92d1a3b230492fea7e6f2af739dc158a7fbd29856cbedb57b4119e64b27ab09eb1c2df01507d6e7fd +A = 4c653b5bfec44e9be100c064dffe5d8cd59b0cf4cc56b03eabb4ef87cfda6506c9a756b811907fe9d8b783eb7a0b9e129773bf1da365ddb488d27b16fb983e89345d1ccdb4f06a67a11925c3f266373be5d7b0075189c6f3c2157e2da197058fe0a7bcc50adc34e99e254a29abbe2d5948d3157e1b0c3fca3d641760f7b9862843b63abef0b3d83fd486f4526b30382fda355575da30e9a106718a3921774c4d69f5311f8d737fe618f5236b4763fe1b2ee7f13184db67367d3903c535ff6d7b +B = 2dcca83c99a28e9fd2f84e78973699baf2f04fd454094730948b22477834a0064817b86e0835e6d7b26e5b0b1dcf4ad91a07ac0780d6522df1fcac758cf5db6c2a5623d7c0f1afefd5718f7b6de639867d07a9ec525991304e9355d1635104bea837f74758d6aa2aab4e4afbb606af1d98de7417505e4710cd0589bdff9a0bf38a857cc59a5f1781043e694fc2337fd84bdeb28b13a222bb09328a81ec409ad586e74236393d27398cc24d412135e34247c589149e134b97f4bd538ac9a3424b +LCM = 1760c0b0066aa0695767099e87e9388729ea89b8e8c36bddcd04d257591e741613c07b0e69447c0a468c33a745084171e06523d987d8db40a1433bf435325e8a724a0876503b34495170ff3671d42117a2e4f3a75b1d9dd809a34fa0fb26fe50d84f80a9b02e40190e5efb927a5a61a03f13edbce2e666af6c3a2a9bcb84e47e3090008753ff27c4b8cf06480f471379a93f5230923623a83b286b71a555cd5e5347282f664ed90b14b2c4de84a70375e488211a7b3931119ef3bbe029b712389fe784818a0bf29d80733ce9cc940c547aa1eb3f06d492eb676bf37802283c82ce76156dfaab5c2d5107e08062681b5fa169f6eb68e1ab8bd9b2005e90bd4fd + +GCD = 244b9b1290cf5b4ba2f810574c050651489f2d3a2b03e702b76ebfaf4e33de9bbe5da24c919e68d3a72eadd35982b3a89c6b18b38ff7082ac65263e52b6ec75a5717b971c98257b194c828bff0216a99536603b41a396ea2fb50f5ea7cf3edf10bb0d039123e78593ae9ffcbbba02e51e038533e83b6bc73c70551d6467f39809 +A = 41a0b1310669500681cdf888836f6c556758750f562d743ac780dd4c0d161856380e44fdbb1f8a2786bf45be6b0e7f1cb2cd85f6b9e50acc72793d92383c7d7fb796fc74d32e8fac8225bdc19ae47546d9c9c75f5f06ca684f07daccaf89ccf2cddeb7ec255d530c7dd1e71daf44cafdc9d30fbcb1cbaefae3480585f79f4177e3834a5bc91845e2e8cd8aeb27f484e5e5b2c3c076dbb6c23e91303f0a0fdde83cd33a8ea6ed1549e727b4d766c1017c169710fd98e1585d60f66e121f9180b3 +B = 251f5aeaa60b3959285f49540cdaf8e21451110bbddb9933bbbcaea3112f4eb45e435a3ba37c52d2ab79ce997a8f6c829b3aa561f2852924b8effb52396d09d2bf257ebb4fb56c7aa25648f69b06d2cd01e876c9f9c0679de9e6fffa79eb7e603723e5af7de46ee405a5a079229577b5b6fffb8d43e391fe6f4eb89638e64d6eff8026249aaa355a91625eb0bfd14caa81e4c3586aaa2e94fde143a44f223a91e226661d12f55dfcdb4215e5a64e14e968005733be6a71c465de312ca109b34a +LCM = 431f918b274f3e43f446e4e85567883d6536a0332db662cef088f5a36b0f4b68372048174ba10fee94b9f8f1c2e189c974be2e6e8ae8e2ae108445326d40f63e38d8d4e2e46174589a3cbc9583e0036dc8146e79eee9e96f4436313b3f143dd0f5aceab05243def7f915169c360f55ef123977cf623c5ba432c3259c62fb5e37d5adab0f24b825aa4ada99ec4e83e9ca4698399e1ed633091ce5f9844c540a642cd264201116ed4168aa2105a5159f5df064f845830c469140f766c7319052ce59bd1ad7c3f2d8c30e54f147f6aeb5586c70c984302ba18d854a60aec01b394c7d66fa33fe18fe4a8cfb3238df219294e6e42190a30d28b10049a1b75853a4e + +GCD = 206695d52bc391a4db61bf8cb6ea96188333a9c78f477ee76976c2346dad682cf56ca6f176d86ef67d41ff5921b6162b0eca52359975872430dd14c45643eacdf028d830770714c033fd150669705851b2f02de932322d271d565d26768530c3f6cb84f0b3356f970b9070b26c050ead0417152c324c8ffe266d4e8b5b7bef3a +A = 1114eb9f1a9d5947eb1399e57f5c980833489685023ed2fe537fe1276c1e026b9a19e6fff55aa889d6c4e977b6e6f3111e2ad463138637b50f42cf32e57d83f282de9e72f813e5969195159a666d74dcd689bd527c60199ae327f7bd548ac36868fea5fdf6f35d19b921e7c10b6448ca480de6826478cd0642d72f05af3f8e65ce42409fbd49f56e81946e89c8e83962c4edc0ed54600600a305e52d081aed3c351e450e11f8fb0ce5754c92cf765b71393b2b7a89c95df79b9ea1b3cb600862 +B = 1d8f3179ca7b5cc7119360c10de939ffa57c9043da2f2b0ca3009c9bdad9f19ed16e3c2c197bef4b527fa1bf2bbab98b77e26c329911db68bd63d3d0fbfc727a977395b9ad067106de3094d68e097830858c5ccfa505fc25e972bdee6f347e7d1163efacd3d29a791ec2a94ffeed467884ae04896efc5e7e5f43d8d76c147e3c9951a1999173bc4e5767d51268b92cc68487ba1295372143b538711e0a62bf0ac111cc750ca4dd6c318c9cbe106d7fc492261404b86a1ba728e2d25b1976dc42 +LCM = f9570211f694141bfb096560551080cbe02a80271b4505591aaea9e3b99ea1d5ac1c1f2378fd72799e117ac2a73381b1ad26314e39972164d93971479ee3ba21a4d98cef0bd299d540ce5826995dcee0de420dff73d30b23cbf3188c625c7696df517535bc5675d71faa00807efbebdca547933f4a37849d1c014484a77da6df0670c4974bcc91eb5f5fe5faf9dd095ef195ec32ad9eeebf0e63288b4032ed9e70b888afc642f4ff96f0b4c0a68787301c12e4527fe79bdfe72dd3844ab5e094a9295df6616f24d1b9eeebc2116177dacf91969dda73667bc421ef3ccd8d5c23dddc283f5d36568d31f2654926be67f78e181075bdc148f2b39c630b141ae8a + +GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +A = 0 +B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +LCM = 0 + +GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +B = 0 +LCM = 0 + +GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 +LCM = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 + +GCD = 2 +A = 14e95a85e59ade9ef39e2f400c65db18702fa5fc485b9bba479a5282b2206129160e54f73ef4917983c17b4c5ebff7be112a886de069706eee29ba902515cb038 +B = ddcfff1d39c90c599f55495bf71c1e7597c6b08b7430707f360c6a6e5137bbc7b403c6d9e2c34f3d2f29d5d32b869346853c2de239cc35381bdfb4a01569211a +LCM = 90f38564ee72e55d362c04599e7d74f068c75f541b84e97abba2841f1a9f66b06b5c9009f6a4c2e319fced85270588de03ccebddbd9279aaecb13bdc1dbea7f42acaee751cb7da83779b8785cc86f41b94b13b54964208ca287d981634778d1096f20e76ca636c0717fd27e0800c43f599a5eded807421b502eaf9990a8c8ed8 + +GCD = 4 +A = 3c719c1c363cdeb7b57c2aabb71f425da4c3e6d3e447204d555e7cf0f3d372bdda906f36078045044978dafc20171767c8b1464d52dfdf3e2ba8a4906da033a8 +B = 30fe0ef151ac51404e128c064d836b191921769dc02d9b09889ed40eb68d15bfdd2edea33580a1a4d7dcee918fefd5c776cbe80ca6131aa080d3989b5e77e1b24 +LCM = 2e4526157bbd765b0486d90bcd4728f890bc6dbd9a855c67ca5cb2d6b48f8e74e1d99485999e04b193afca58dbf282610185d6c0272007744ff26e00dbdc813929b47940b137dc56ba974da07d54a1c50ec4a5c2b26e83f47cf17f4ccce8c3687e8d1e91d7c491a599f3d057c73473723ce9eee52c20fe8ae1595447552a7ee8 + +GCD = 10 +A = 44e04071d09119ea9783a53df35de4a989200133bb20280fdca6003d3ca63fdd9350ad1a1673d444d2f7c7be639824681643ec4f77535c626bd3ee8fa100e0bb0 +B = ca927a5a3124ce89accd6ac41a8441d352a5d42feb7f62687a5ebc0e181cc2679888ecc2d38516bdc3b3443550efccac81e53044ae9341ecace2598fe5ce67780 +LCM = 36805ba9b2412a0cb3fe4ed9bdabfa55515c9d615a3d0af268c45c5f6098d2de4a583f3791f1e3883c55d51ce23c5658fd0e8faa9a3709a1cfbd6a61dbab861690f27c86664f084c86cfd4a183b24aaadf59a6f8cbec04f1b0ded8a59b188cb46ae920052e3e099a570540dbc00f7d4a571eef08aa70d2d189a1804bf04e94a80 + +GCD = 100 +A = 73725032b214a677687c811031555b0c51c1703f10d59b97a4d732b7feaec5726cb3882193419d3f057583b2bc02b297d76bb689977936febaae92638fdfc46a00 +B = 979f4c10f4dc60ad15068cedd62ff0ab293aeaa1d6935763aed41fe3e445de2e366e8661eadf345201529310f4b805c5800b99f351fddab95d7f313e3bb429d900 +LCM = 4460439b4be72f533e9c7232f7e99c48328b457969364c951868ceab56cb2cbbeda8be2e8e3cae45c0758048468b841fdb246b2086d19b59d17b389333166ab82ed785860620d53c44f7aaaff4625ee70fb8072df10fb4d1acb142eadc02978ff2bb07cea9f434e35424b3323a7bda3a1a57aa60c75e49ebb2f59fb653aa77da00 + +GCD = 100000000 +A = f8b4f19e09f5862d79fb2931c4d616a1b8e0dd44781ca52902c8035166c8fca52d33a56ff484c365ec1257de7fa8ed2786163cfc051d5223b4aad859a049e8ba00000000 +B = 6e54cb41b454b080e68a2c3dd0fa79f516eb80239af2be8250ca9cd377ba501aabafc09146fad4402bdc7a49f2c3eec815e25f4c0a223f58e36709eefd92410500000000 +LCM = 6b3020a880ddeff9d17d3dc234da8771962de3322cd15ba7b1e4b1dd4a6a2a802a16c49653865c6fdf6c207cbe0940f8d81ef4cb0e159385fd709d515ee99d109ad9ad680031cbae4eab2ed62944babdade4e3036426b18920022f737897c7d751dce98d626cdda761fec48ad87a377fb70f97a0a15aa3d10d865785719cc5a200000000 diff --git a/crypto/internal/fips140/rsa/testdata/miller_rabin_tests.txt b/crypto/internal/fips140/rsa/testdata/miller_rabin_tests.txt new file mode 100644 index 00000000000..10e9685a615 --- /dev/null +++ b/crypto/internal/fips140/rsa/testdata/miller_rabin_tests.txt @@ -0,0 +1,344 @@ +# This file contains test vectors for whether B is a Miller-Rabin composite +# witness for W. W must be odd and B must satisfy 1 <= B <= W-1. +# +# It was copied from BoringSSL's crypto/fipsmodule/bn/test/miller_rabin_tests.txt, +# removing out-of-range candidates that we reject within the iteration function. + +# Exhaustively test a small prime. + +Result = PossiblyPrime +W = 7 +B = 2 + +Result = PossiblyPrime +W = 7 +B = 3 + +Result = PossiblyPrime +W = 7 +B = 4 + +Result = PossiblyPrime +W = 7 +B = 5 + + +# Random large inputs which try to cover a few cases. The nontrivial square root +# case appears to be difficult to hit randomly. + +# b^m = w-1 +Result = PossiblyPrime +W = d6b4ffc7cf70b2a2fc5d6023015875504d40e3dcce7c2e6b762c3de7bb806a5074144e7054198dabf53d23108679ccc541d5a99efeb1d1abaf89e0dbcead2a8b +B = fabbafdbec6494ddb5ea4bf458536e87082369b0e53a200ed413f3e64b2fddc7c57c565710fbe73fae5b188fce97d8dcca74c2b5d90906c96d3c2c358a735cd + +# b^m = w-1 +Result = PossiblyPrime +W = 52cc61c42b341ad56dc11495e7cb2fe31e506b9e99522efbf44cd7c28468d3833c5e360f3c77b0aa43c0495c4e14665ab0d7cee9294c722f0de47d4401828401 +B = 3bdc9639c0fc2e77ab48d46e0b4ac6529c11c900e8fe4d82d75767c0556feb23d3f42d4924d16876a743feb386b7b84c7fd16a6c252f662faf0024d19972e62f + +# b^m = w-1 +Result = PossiblyPrime +W = cff9897aa7dce0f2afad262b2de57d301305de717f3539c537c4ce062f8cb70df13fbc1eb4a3b9f0958a8810d1ca9042b4f23334b285a15fee3fc66498761d4b +B = 9ceb43132fddf9ee4104ea1cb3eb2253c1d7f803f05f0305de9e31a17dd75832f47b8bf189a9b7ca0905f2a7470d9c6349080f481ff1708696fa12d972e7d7ba + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 67d1825dad5344170e65247a87aef1634a1b32bdc22f2f04d9d2959767bb5a27610fba55cd607e0f9fdd9fbb0f7f98e40d5e1eb2f52318fb5be4dbfd30d38861 +B = 260fb14724ff80984736859d8755ee98b25bcb56db9fde1db001a1e1273374034c5b75fd60b3710c7a08ce7d390776f010f384d4e32943cf0c477497d53e9e05 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = ad0bc85b58aaa204177aa9431a40929beb1cbea2dd6f66a25cc54600013213b225ba881805661df43f4208965ada7aacc8095d07d3cbef1a7bbfaae8b745f731 +B = 3d9310f20e9c80269fa6830c7e1a6f02fc5c58646001a9ef6b8b3e496602ff22c3dcb2ddb6a221723fc1722ce237fb46f7a7bb2945e415c8839b15a972f076c9 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = b25c917f55f6c7b596921daba919f35039e5d805119c1587e99849dd7104460c86214f162a6f17aea847bc7f3859e59f2991d457059511972ef373d4bc75e309 +B = a1f10b261dee84619b0423201d46af19eef9ec0612cf947c4d5c36c0c4b28207f75967e69452eabad0a5dcd28f27f7a8a7ed9c8b3e5026c6e0ba5634d94c2d44 + +# b^m = 1 +Result = PossiblyPrime +W = d3eeb0eff05b6992e9fa61b02755e155f4aae28c6e45ddb874edd86acdd2d83d18a20e0e00d8b8bc94b92d14fc3f41ced6ababe8ac98c7730c075dbe0f699369 +B = 6b7717269c6225203681a1cacec87cacd83003ec6e9e3f04effcc4f86634770c0860e1f2770b8f303719a44949664a1094205a99d95a0856758fed66d690105e + +# b^m = 1 +Result = PossiblyPrime +W = 64561b8d9aa50340c3a01ccb3e6e17f5023513661c012be288f3900a3ca76890e67290b9560fa1d480f9d2aacccca581b5690636665f243fa13aff5d0bff12d3 +B = 1f5ff70d3d60671ebc5fbfca731898a04438053dbc3c841e6335f487e457d92d9efb5d506d5bef6872d58d12b9a41c950bfc38d12ed977c90eacdd6535b811a0 + +# b^m = 1 +Result = PossiblyPrime +W = 69c63fbf44df21b0ed0ee929a740c12d1f3f064da0dcd9d509f31fa45fa27d1a759ab5a9f6f1040d7ee90a0b1e68f779273c41ea1c1198fd547ff6bd70c7e787 +B = 5f7996a9bbfd8fd88e472220b70077bfdacdd63d88885134431f024c2acb7126827b174eb093eb5313f07bb5461de9b0feb7d77ca2c39c2a323a150f33ea525f + +# End of iteration +Result = Composite +W = 28cc3e08c44571c6dcb98a9ab8b4f3e2b16e1f884997d94a3188bcbb7f1b7cdaecdae8329c013ec8f75dc00004da0039943e4262cd080b16a42910102e00dddb +B = 512061ab1c69931c2fa0bb89d8d09f3c9209230bf927ddd6fb6a72075f967ed3c4dbb5f437bf4d31ca7344782b22011ad56609dc19aed65319bababfc13dd7 + +# End of iteration +Result = Composite +W = 4eeb7b4d371c45fe8586fee3b1efd792176b70f6cc2698dfa1dd028366626febe0199c3c5f77a5c3cad0057a04767383051d41965255d03681b2a37edad34a9b +B = 4afc2e85f84017b3fd6967a227eb74c8297b40ea02733d9513bff9b3f01081963f25872f4254afc4e9321eea35b2a1e42eadb186fcc84f2f30f4a994350b93b8 + +# End of iteration +Result = Composite +W = 8e35a959555dd2eb66c65cee3c264071d20671f159e1f9896f1d0ceb041905fcf053eacc189de317c3ee6f93901223cbf30d5b7ddbbdab981790e2f6397e6803 +B = 44c0153759309ec4e5b1e59d57c1b126545ef7ea302b6e43561df4d16068b922389d6924f01c945d9080d1f93a0732599bdedae72d6d590839dc0884dd860441 + + +# 0x6c1 = 1729 = 7 * 13 * 19 is a Fermat pseudoprime. + +# Found non-trivial square root +Result = Composite +W = 6c1 +B = b8 + +# End of iteration +Result = Composite +W = 6c1 +B = 111 + +# End of iteration +Result = Composite +W = 6c1 +B = 11d + +# Found non-trivial square root +Result = Composite +W = 6c1 +B = 19c + +# Found non-trivial square root +Result = Composite +W = 6c1 +B = 223 + +# End of iteration +Result = Composite +W = 6c1 +B = 3aa + +# Found non-trivial square root +Result = Composite +W = 6c1 +B = 653 + + +# 1729 has a number of false witnesses. + +# b^m = 1 +Result = PossiblyPrime +W = 6c1 +B = 78 + +# b^m = 1 +Result = PossiblyPrime +W = 6c1 +B = eb + +# b^m = w-1 +Result = PossiblyPrime +W = 6c1 +B = 178 + +# b^m = w-1 +Result = PossiblyPrime +W = 6c1 +B = 178 + +# b^m = w-1 +Result = PossiblyPrime +W = 6c1 +B = 1aa + +# b^m = 1 +Result = PossiblyPrime +W = 6c1 +B = 271 + +# b^m = 1 +Result = PossiblyPrime +W = 6c1 +B = 2b2 + + +# https://kconrad.math.uconn.edu/blurbs/ugradnumthy/millerrabin.pdf, examples +# 3.1 and 3.2 has a complete list of false witnesses for 65 = 0x41 and +# 85 = 0x55. + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 41 +B = 8 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 41 +B = 12 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 41 +B = 2f + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 41 +B = 39 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 55 +B = d + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 55 +B = 26 + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 55 +B = 2f + +# Some b^(m*2^j) = w-1 +Result = PossiblyPrime +W = 55 +B = 48 + +# Other witnesses for 65 and 85 will report composite: + +# Found non-trivial square root +Result = Composite +W = 41 +B = 2c + +# End of iteration +Result = Composite +W = 41 +B = 16 + +# End of iteration +Result = Composite +W = 41 +B = 14 + +# End of iteration +Result = Composite +W = 41 +B = 2 + +# End of iteration +Result = Composite +W = 41 +B = 3a + +# End of iteration +Result = Composite +W = 55 +B = 40 + +# End of iteration +Result = Composite +W = 55 +B = 7 + +# End of iteration +Result = Composite +W = 55 +B = 23 + +# End of iteration +Result = Composite +W = 55 +B = 2e + +# End of iteration +Result = Composite +W = 55 +B = 2a + +# W below is composite, but it is one of the worst case scenarios for +# Miller-Rabin, from Wycheproof tests. 1/4 of witnesses report the value is +# prime. Test that we correctly classify false and true witnesses. + +# b^m = w-1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 379c6027f818b5164bc13dff5e996ec7210976f33570d5c60275918b8988d97a63bb6582af85682c45667a8b94b7acab4d919ede00f5bd2ba7abc8634d66f8875fd930f35ec8013d37b958e65f07de015c0574e64198d73aab5466f3a971b74830b7f1671cb9277fbc95c1ba8c29dc903d8cea1b74c22ab9164f9c438ab9ba7d9919f832e40c3e36faca7343e2314669b0104d9c4f2e1b011cdbd9c686baef0 + +# b^m = w-1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 3cc4b644965b2133caffc2bb6258b1ecd5b586b900a09b010382fcef709e4cd37ee3e3182bf8d393c1ab6f9a933d46338b3d960923d8c9607c2b2763d5680230a2bc0c91138e9d0ecb35e7154a06aaa902d34b9b14964b81f4d8232641492d83b22cd805a115e75ddd8e63b864c00e4c90ba36a41e7966e97e063a60a6a6cfd53e1f62a57852c7443e88dcf6245557a4b65494c3e88e466ad75316aaa9727def + +# b^m = 1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 40c03b6ba22bd62c0379b1c36dfccd34d61e3d15f7af1d5f6a60ab972a9d0e956e2bb9e275294e0f1c879eb7a4555443429c99a8d74f7bd359a1046ac30072c04b0e2cbd005be15ff4ce0c93276de2c513fbc5771b5059904a87f180530f6773498114b5aaf70da01967d8294742e451df6377dd5e64b2a8968f4ba61b51a154317d63958ff3788defbeeebee21af5027c2291e8c5df8c0b66770d91b683cffe + +# b^m = w-1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 3c7c71b84f0c6c3817f57511946315cec7d0120a9c30ceabda801fbaec329a8f10c7b9f0ae90a3dada9885bf73a3cabed86784af9682f3dea50a7817f65cfc9190cf997f12784223c4965ed6e52a1be26d4dde31741cd3d1a2e2f3a74040d0f3868eef849727aa855f66c94791194ad5d360298364e2de9ca9288e6423f644b01d52e1bd66a9f7f00bd7995a9ca2ed16f40e902852c6250a3b52bbbf5bfd33e8 + +# b^m = w-1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 36e6aa9acb399a50f52be0324dcef05f3cff3117f94538f6d0952b7d7be88ba4dc75d843ff7ff775e11f55c86ba6b2a6ddebd8850c33424b4d35c66321af426662e7074f0a2409a9ccf1c66ef7d823efc8240b8f3c7e9e8dd65a64e8a3ca5b26695ef17171ffe136c0593b179414c5b5ad0d66f2a25146c38b2f97e60b0472ed72de34bff1b6ac186f23645a1bbe909cdfc2b2d861eb44931568f1bb117d8a0c + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 278f2215d3ab836043fbfa472216bbdcedb775a6a0ed711754d05aa75089a9e5d8201e113d68656f37381e44483cd365f5d383bdca5ae8d1f2e6575d7873851cfff0e12b1cfe100a04cb300cbd924353fcbd3307d01242cf6a5e86e752c6f4586bcabf48b018bb97e65c3ed409fd6f67f98987517356d88344b3c8945ccd753148a37b648dd2db44d19522a69a9ad8eb23edc55340e85a198abf179ad731db41 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = afa1478bebbfe1157568f4ae53549b4c3a6a8771b816970bfac6ce5c8b962231db7a41da4d5f1d8bf504dcfe440325b54e1888bdae344eb969436a35e5c6ce5300d46313cb2fcb57fc83305f65f53d392de400e9231cbbc2ac8243defcaf7063c632b9601a81d83138274702ff336d727d3e82ccacce069843ac9c1c590c772c8c586b65c7085a1df5a47fc960d4098a22418b41f0062c77b5d55d17149d167 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 10f7030590b629e0313a61bdf46936a1f25db91b2b421f7ebb671f7844c22561b44b2f7699db61e5228ebb5817afad416325f9439eff7a82d8a630c504de12eaa44d97c79ee56e726ae74ee0b472f0d5fa8f20aee426e689cd33dd084f96bf4d928a21e815f7e8aaca4a5752f39c4a76bdfaa8227dc05d0dfa885d8b26d46fbcbf0d2e0d999d2c31ad84c306c9126539dbdf447f8dc707d29c7fa8021a767668 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 97dbb6a55c039ec926aaa5ff15a2917a2b4cafc3ca07c4c6b05f931d86c9bf60ee05cbbace194e5ca97682ec67c36394018d68c3536fbf13b50f8a7e31eaed87307759a0a48c6c58d21bc7c38b878c53db5d7a8e1fdd81abefc50470a3800852e74d76fdd1933e45f39ee97b8efb68837721890d867b32a894dd0ceb4c5844a05d384145865c10973ce748ccdd8fee73f1bf8611ce0535430b6b98fb36cad7a + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 225f58add44ed2b0a64a1d8452866d0f3c0cd45c8375e1bb33c188915c77fa11b81250b920245dda7f6126e5e0c79e6f98f89dc15db86394cf81b44f0d801e613fa4d5c6fef66fa31f26cfe6153f2e8159aad6b0351dcc0e93f9a68f649b2a77cff747b605b542d22419166befebec6cde3201e3c0cacaa2bc9d87073b8d1f1aa2b114d61de45ac8b0ad2141b43434a629ef284cd999fd82b310db7c57cf5c81 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 2780926c9cf7c1eb2aaa935d90b6d4dea44eeefdfcf9ccd4a33feb215e3a1cb2d358136a490fed18403947f3d98807819737c66e12d42c3cc8c0e246b96b3c3b0795ab875fbaf668b81b5b05bf23e258ea00a0a140a790f76e04ab619800b7597f614ffc1a1c94be2f3f1a71d64eb47d98e4653d76eabedacff3a97ecf590e6a1fd55096b7bc9314629f698d0fbe9b01a1f2bc0bf3a2c097f99f1fd222b52ed2 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 129cc5b0d9f8001b3895f1fcb4833779763636aeeeb3f980e63ea506202e6bde868444b6a58ff1dca08625f025a7e95a5eaaf1a8899eee640e3f05fbdb2867e2483bdc27c87b58684416e521c107f3667ed8dd23f0381edab767c5205a4378118bc011947cb6bdfe3fa4af50b8de876b555c9a0b2b0dae01261847f63e1e0cac2d032530bf19d5da60a04dfe22ce6343f60defbb94ccf0bdf010f89a4029720 + +# b^m = 1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 4e2a47cf67c3331b1e9976f583f6339cf76a8d48682d01355c25b2aed90c5544e737ecfa849c17d27a64fad7e659ef48df9a3ac0410e5c7ca8d087fc3a3ba23e5a3f000be009fcc8227ead28158c5b5d66f2efb47111638ef61cea4984de42fbd476bc2236ad02154d3ce85805c45e49d16b496e313a4052a37d4b88a3b13e598d2074a3e36a37e90278601f2b2305e034f9bf3aea8e939c3ba274e8ff4d8a14 + +# b^m = 1 +Result = PossiblyPrime +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 2455c4ab826e2ae72708a8ff51348ce4821cb86fa89e298c751c1754211c63b2e9a712d40f0235f310606fcf296726a86973f19f890d571f5b90f026e8d24d07bc0478a3c1333171587387f1f7fe4a770b593216f2743318aabacb3320c40a4e52b9f409e1176fe8db099e93a7991eb8568168e2e486fa5aa228bb1dce9df3290ef13fd21c331479bb0f8b7a7e7f03c5211ae8cc46fa4d0f46e86b2dadeddd5b + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 9951c2c02dd7deedce29bd0c78dd80066b1d69c0e6fe4a17f7d03c6a640d866d01fc8214bafb6737efd93d80a35b8993f5367ce287459b07954e9771ffbc72ccdd812d26a9bf4be0292a24eb5c3b56f09619b1c1b481f7566f7e50e65f69f5feb591bd107fec72a783429dbde6e2607f3db2c58d4b070a45b4d6b43537e19942ce890b04ae1e91069c04a96ed03ddb2f4fc456f136b98102c70a15700dbd911 + +# End of iteration +Result = Composite +W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87 +B = 4cb8217d229d5f95f6d94807a99363823655d6bba6bdafa4f0dbfe7a5c538aa79c918710aad4f55caaee5ab405ebdcef29dfb76cae99fca8d5a955b6315f71a3cb2d69a217ff45aed66ba87cdc5c0de5d512c6dd12e641e9fe6a2557dd2f03bf3a18650ff139efa179f0fbe69cbb4b54e50d13177bfe7bb90de36b548d5ccfef74b05d3c08a7e2a3bb4dc8d7eb338a7a1b068c433ea204d171eda5e7c6b6722c diff --git a/crypto/internal/fips140/sha256/_asm/go.mod b/crypto/internal/fips140/sha256/_asm/go.mod new file mode 100644 index 00000000000..eb93418b8a1 --- /dev/null +++ b/crypto/internal/fips140/sha256/_asm/go.mod @@ -0,0 +1,11 @@ +module crypto/sha256/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/sha256/_asm/go.sum b/crypto/internal/fips140/sha256/_asm/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/sha256/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/internal/fips140/sha256/_asm/sha256block_amd64_asm.go b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_asm.go new file mode 100644 index 00000000000..a3324673fdd --- /dev/null +++ b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_asm.go @@ -0,0 +1,132 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "os" + + . "github.com/mmcloughlin/avo/build" +) + +//go:generate go run . -out ../sha256block_amd64.s + +// SHA256 block routine. See sha256block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 63 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +func main() { + // https://github.com/mmcloughlin/avo/issues/450 + os.Setenv("GOOS", "linux") + os.Setenv("GOARCH", "amd64") + + Package("crypto/internal/fips140/sha256") + ConstraintExpr("!purego") + blockAVX2() + blockSHANI() + Generate() +} + +var _K = []uint32{ + 0x428a2f98, + 0x71374491, + 0xb5c0fbcf, + 0xe9b5dba5, + 0x3956c25b, + 0x59f111f1, + 0x923f82a4, + 0xab1c5ed5, + 0xd807aa98, + 0x12835b01, + 0x243185be, + 0x550c7dc3, + 0x72be5d74, + 0x80deb1fe, + 0x9bdc06a7, + 0xc19bf174, + 0xe49b69c1, + 0xefbe4786, + 0x0fc19dc6, + 0x240ca1cc, + 0x2de92c6f, + 0x4a7484aa, + 0x5cb0a9dc, + 0x76f988da, + 0x983e5152, + 0xa831c66d, + 0xb00327c8, + 0xbf597fc7, + 0xc6e00bf3, + 0xd5a79147, + 0x06ca6351, + 0x14292967, + 0x27b70a85, + 0x2e1b2138, + 0x4d2c6dfc, + 0x53380d13, + 0x650a7354, + 0x766a0abb, + 0x81c2c92e, + 0x92722c85, + 0xa2bfe8a1, + 0xa81a664b, + 0xc24b8b70, + 0xc76c51a3, + 0xd192e819, + 0xd6990624, + 0xf40e3585, + 0x106aa070, + 0x19a4c116, + 0x1e376c08, + 0x2748774c, + 0x34b0bcb5, + 0x391c0cb3, + 0x4ed8aa4a, + 0x5b9cca4f, + 0x682e6ff3, + 0x748f82ee, + 0x78a5636f, + 0x84c87814, + 0x8cc70208, + 0x90befffa, + 0xa4506ceb, + 0xbef9a3f7, + 0xc67178f2, +} diff --git a/crypto/sha256/_asm/sha256block_amd64_asm.go b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_avx2.go similarity index 72% rename from crypto/sha256/_asm/sha256block_amd64_asm.go rename to crypto/internal/fips140/sha256/_asm/sha256block_amd64_avx2.go index 549906272d5..0e6f1c74cf5 100644 --- a/crypto/sha256/_asm/sha256block_amd64_asm.go +++ b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_avx2.go @@ -10,14 +10,6 @@ import ( . "github.com/mmcloughlin/avo/reg" ) -//go:generate go run . -out ../sha256block_amd64.s -pkg sha256 - -// SHA256 block routine. See sha256block.go for Go equivalent. -// -// The algorithm is detailed in FIPS 180-4: -// -// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - // The avx2-version is described in an Intel White-Paper: // "Fast SHA-256 Implementations on Intel Architecture Processors" // To find it, surf to http://www.intel.com/p/en_US/embedded @@ -29,154 +21,223 @@ import ( // Kirk Yap // Tim Chen -// Wt = Mt; for 0 <= t <= 15 -// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// -// a = H0 -// b = H1 -// c = H2 -// d = H3 -// e = H4 -// f = H5 -// g = H6 -// h = H7 -// -// for t = 0 to 63 { -// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt -// T2 = BIGSIGMA0(a) + Maj(a,b,c) -// h = g -// g = f -// f = e -// e = d + T1 -// d = c -// c = b -// b = a -// a = T1 + T2 -// } -// -// H0 = a + H0 -// H1 = b + H1 -// H2 = c + H2 -// H3 = d + H3 -// H4 = e + H4 -// H5 = f + H5 -// H6 = g + H6 -// H7 = h + H7 - -func main() { - Package("github.com/runZeroInc/excrypto/crypto/sha256") - ConstraintExpr("!purego") - block() - Generate() +func blockAVX2() { + Implement("blockAVX2") + AllocLocal(536) + + Load(Param("dig"), CTX) // d.h[8] + Load(Param("p").Base(), INP) + Load(Param("p").Len(), NUM_BYTES) + + LEAQ(Mem{Base: INP, Index: NUM_BYTES, Scale: 1, Disp: -64}, NUM_BYTES) // Pointer to the last block + MOVQ(NUM_BYTES, Mem{Base: SP}.Offset(_INP_END)) + + CMPQ(NUM_BYTES, INP) + JE(LabelRef("avx2_only_one_block")) + + Comment("Load initial digest") + CTX := Mem{Base: CTX} + MOVL(CTX.Offset(0), a) // a = H0 + MOVL(CTX.Offset(4), b) // b = H1 + MOVL(CTX.Offset(8), c) // c = H2 + MOVL(CTX.Offset(12), d) // d = H3 + MOVL(CTX.Offset(16), e) // e = H4 + MOVL(CTX.Offset(20), f) // f = H5 + MOVL(CTX.Offset(24), g) // g = H6 + MOVL(CTX.Offset(28), h) // h = H7 + + avx2_loop0() + avx2_last_block_enter() + avx2_loop1() + avx2_loop2() + avx2_loop3() + avx2_do_last_block() + avx2_only_one_block() + done_hash() } -// Wt = Mt; for 0 <= t <= 15 -func msgSchedule0(index int) { - MOVL(Mem{Base: SI}.Offset(index*4), EAX) - BSWAPL(EAX) - MOVL(EAX, Mem{Base: BP}.Offset(index*4)) +func avx2_loop0() { + Label("avx2_loop0") + Comment("at each iteration works with one block (512 bit)") + VMOVDQU(Mem{Base: INP}.Offset(0*32), XTMP0) + VMOVDQU(Mem{Base: INP}.Offset(1*32), XTMP1) + VMOVDQU(Mem{Base: INP}.Offset(2*32), XTMP2) + VMOVDQU(Mem{Base: INP}.Offset(3*32), XTMP3) + + flip_mask := flip_mask_DATA() + + VMOVDQU(flip_mask, BYTE_FLIP_MASK) + + Comment("Apply Byte Flip Mask: LE -> BE") + VPSHUFB(BYTE_FLIP_MASK, XTMP0, XTMP0) + VPSHUFB(BYTE_FLIP_MASK, XTMP1, XTMP1) + VPSHUFB(BYTE_FLIP_MASK, XTMP2, XTMP2) + VPSHUFB(BYTE_FLIP_MASK, XTMP3, XTMP3) + + Comment("Transpose data into high/low parts") + VPERM2I128(Imm(0x20), XTMP2, XTMP0, XDWORD0) // w3, w2, w1, w0 + VPERM2I128(Imm(0x31), XTMP2, XTMP0, XDWORD1) // w7, w6, w5, w4 + VPERM2I128(Imm(0x20), XTMP3, XTMP1, XDWORD2) // w11, w10, w9, w8 + VPERM2I128(Imm(0x31), XTMP3, XTMP1, XDWORD3) // w15, w14, w13, w12 + + K256 := K256_DATA() + LEAQ(K256, TBL) // Loading address of table with round-specific constants } -// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// -// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x) -// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x) -func msgSchedule1(index int) { - MOVL(Mem{Base: BP}.Offset((index-2)*4), EAX) - MOVL(EAX, ECX) - RORL(Imm(17), EAX) - MOVL(ECX, EDX) - RORL(Imm(19), ECX) - SHRL(Imm(10), EDX) - MOVL(Mem{Base: BP}.Offset((index-15)*4), EBX) - XORL(ECX, EAX) - MOVL(EBX, ECX) - XORL(EDX, EAX) - RORL(Imm(7), EBX) - MOVL(ECX, EDX) - SHRL(Imm(3), EDX) - RORL(Imm(18), ECX) - ADDL(Mem{Base: BP}.Offset((index-7)*4), EAX) - XORL(ECX, EBX) - XORL(EDX, EBX) - ADDL(Mem{Base: BP}.Offset((index-16)*4), EBX) - ADDL(EBX, EAX) - MOVL(EAX, Mem{Base: BP}.Offset((index)*4)) +func avx2_last_block_enter() { + Label("avx2_last_block_enter") + ADDQ(Imm(64), INP) + MOVQ(INP, Mem{Base: SP}.Offset(_INP)) + XORQ(SRND, SRND) } -// Calculate T1 in AX - uses AX, CX and DX registers. -// h is also used as an accumulator. Wt is passed in AX. -// -// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt -// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) -// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) -func sha256T1(konst uint32, e, f, g, h GPPhysical) { - ADDL(EAX, h) - MOVL(e, EAX) - ADDL(U32(konst), h) - MOVL(e, ECX) - RORL(U8(6), EAX) - MOVL(e, EDX) - RORL(U8(11), ECX) - XORL(ECX, EAX) - MOVL(e, ECX) - RORL(U8(25), EDX) - ANDL(f, ECX) - XORL(EAX, EDX) - MOVL(e, EAX) - NOTL(EAX) - ADDL(EDX, h) - ANDL(g, EAX) - XORL(ECX, EAX) - ADDL(h, EAX) +// for w0 - w47 +func avx2_loop1() { + Label("avx2_loop1") + + Comment("Do 4 rounds and scheduling") + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((0 * 32)), XDWORD0, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+0*32)) + roundAndSchedN0(_XFER+0*32, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + roundAndSchedN1(_XFER+0*32, h, a, b, c, d, e, f, g, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + roundAndSchedN2(_XFER+0*32, g, h, a, b, c, d, e, f, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + roundAndSchedN3(_XFER+0*32, f, g, h, a, b, c, d, e, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + + Comment("Do 4 rounds and scheduling") + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(1*32), XDWORD1, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+1*32)) + roundAndSchedN0(_XFER+1*32, e, f, g, h, a, b, c, d, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + roundAndSchedN1(_XFER+1*32, d, e, f, g, h, a, b, c, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + roundAndSchedN2(_XFER+1*32, c, d, e, f, g, h, a, b, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + roundAndSchedN3(_XFER+1*32, b, c, d, e, f, g, h, a, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + + Comment("Do 4 rounds and scheduling") + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((2 * 32)), XDWORD2, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+2*32)) + roundAndSchedN0(_XFER+2*32, a, b, c, d, e, f, g, h, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + roundAndSchedN1(_XFER+2*32, h, a, b, c, d, e, f, g, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + roundAndSchedN2(_XFER+2*32, g, h, a, b, c, d, e, f, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + roundAndSchedN3(_XFER+2*32, f, g, h, a, b, c, d, e, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + + Comment("Do 4 rounds and scheduling") + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((3 * 32)), XDWORD3, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+3*32)) + roundAndSchedN0(_XFER+3*32, e, f, g, h, a, b, c, d, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + roundAndSchedN1(_XFER+3*32, d, e, f, g, h, a, b, c, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + roundAndSchedN2(_XFER+3*32, c, d, e, f, g, h, a, b, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + roundAndSchedN3(_XFER+3*32, b, c, d, e, f, g, h, a, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + + ADDQ(Imm(4*32), SRND) + CMPQ(SRND, U32(3*4*32)) + JB(LabelRef("avx2_loop1")) } -// Calculate T2 in BX - uses BX, CX, DX and DI registers. -// -// T2 = BIGSIGMA0(a) + Maj(a, b, c) -// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) -// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) -func sha256T2(a, b, c GPPhysical) { - MOVL(a, EDI) - MOVL(c, EBX) - RORL(U8(2), EDI) - MOVL(a, EDX) - ANDL(b, EBX) - RORL(U8(13), EDX) - MOVL(a, ECX) - ANDL(c, ECX) - XORL(EDX, EDI) - XORL(ECX, EBX) - MOVL(a, EDX) - MOVL(b, ECX) - RORL(U8(22), EDX) - ANDL(a, ECX) - XORL(ECX, EBX) - XORL(EDX, EDI) - ADDL(EDI, EBX) +// w48 - w63 processed with no scheduling (last 16 rounds) +func avx2_loop2() { + Label("avx2_loop2") + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(0*32), XDWORD0, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+0*32)) + doRoundN0(_XFER+0*32, a, b, c, d, e, f, g, h, h) + doRoundN1(_XFER+0*32, h, a, b, c, d, e, f, g, h) + doRoundN2(_XFER+0*32, g, h, a, b, c, d, e, f, g) + doRoundN3(_XFER+0*32, f, g, h, a, b, c, d, e, f) + + VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(1*32), XDWORD1, XFER) + VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+1*32)) + doRoundN0(_XFER+1*32, e, f, g, h, a, b, c, d, e) + doRoundN1(_XFER+1*32, d, e, f, g, h, a, b, c, d) + doRoundN2(_XFER+1*32, c, d, e, f, g, h, a, b, c) + doRoundN3(_XFER+1*32, b, c, d, e, f, g, h, a, b) + + ADDQ(Imm(2*32), SRND) + + VMOVDQU(XDWORD2, XDWORD0) + VMOVDQU(XDWORD3, XDWORD1) + + CMPQ(SRND, U32(4*4*32)) + JB(LabelRef("avx2_loop2")) + + Load(Param("dig"), CTX) // d.h[8] + MOVQ(Mem{Base: SP}.Offset(_INP), INP) + + registers := []GPPhysical{a, b, c, d, e, f, g, h} + for i, reg := range registers { + addm(Mem{Base: CTX}.Offset(i*4), reg) + } + + CMPQ(Mem{Base: SP}.Offset(_INP_END), INP) + JB(LabelRef("done_hash")) + + XORQ(SRND, SRND) } -// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. -// The values for e and a are stored in d and h, ready for rotation. -func sha256Round(index int, konst uint32, a, b, c, d, e, f, g, h GPPhysical) { - sha256T1(konst, e, f, g, h) - sha256T2(a, b, c) - MOVL(EBX, h) - ADDL(EAX, d) - ADDL(EAX, h) +// Do second block using previously scheduled results +func avx2_loop3() { + Label("avx2_loop3") + doRoundN0(_XFER+0*32+16, a, b, c, d, e, f, g, h, a) + doRoundN1(_XFER+0*32+16, h, a, b, c, d, e, f, g, h) + doRoundN2(_XFER+0*32+16, g, h, a, b, c, d, e, f, g) + doRoundN3(_XFER+0*32+16, f, g, h, a, b, c, d, e, f) + + doRoundN0(_XFER+1*32+16, e, f, g, h, a, b, c, d, e) + doRoundN1(_XFER+1*32+16, d, e, f, g, h, a, b, c, d) + doRoundN2(_XFER+1*32+16, c, d, e, f, g, h, a, b, c) + doRoundN3(_XFER+1*32+16, b, c, d, e, f, g, h, a, b) + + ADDQ(Imm(2*32), SRND) + CMPQ(SRND, U32(4*4*32)) + JB(LabelRef("avx2_loop3")) + + Load(Param("dig"), CTX) // d.h[8] + MOVQ(Mem{Base: SP}.Offset(_INP), INP) + ADDQ(Imm(64), INP) + + registers := []GPPhysical{a, b, c, d, e, f, g, h} + for i, reg := range registers { + addm(Mem{Base: CTX}.Offset(i*4), reg) + } + + CMPQ(Mem{Base: SP}.Offset(_INP_END), INP) + JA(LabelRef("avx2_loop0")) + JB(LabelRef("done_hash")) } -func sha256Round0(index int, konst uint32, a, b, c, d, e, f, g, h GPPhysical) { - msgSchedule0(index) - sha256Round(index, konst, a, b, c, d, e, f, g, h) +func avx2_do_last_block() { + Label("avx2_do_last_block") + VMOVDQU(Mem{Base: INP}.Offset(0), XWORD0) + VMOVDQU(Mem{Base: INP}.Offset(16), XWORD1) + VMOVDQU(Mem{Base: INP}.Offset(32), XWORD2) + VMOVDQU(Mem{Base: INP}.Offset(48), XWORD3) + + flip_mask := flip_mask_DATA() + VMOVDQU(flip_mask, BYTE_FLIP_MASK) + + VPSHUFB(X_BYTE_FLIP_MASK, XWORD0, XWORD0) + VPSHUFB(X_BYTE_FLIP_MASK, XWORD1, XWORD1) + VPSHUFB(X_BYTE_FLIP_MASK, XWORD2, XWORD2) + VPSHUFB(X_BYTE_FLIP_MASK, XWORD3, XWORD3) + + K256 := K256_DATA() + LEAQ(K256, TBL) + + JMP(LabelRef("avx2_last_block_enter")) } -func sha256Round1(index int, konst uint32, a, b, c, d, e, f, g, h GPPhysical) { - msgSchedule1(index) - sha256Round(index, konst, a, b, c, d, e, f, g, h) +// Load initial digest +func avx2_only_one_block() { + Label("avx2_only_one_block") + registers := []GPPhysical{a, b, c, d, e, f, g, h} + for i, reg := range registers { + MOVL(Mem{Base: CTX}.Offset(i*4), reg) + } + JMP(LabelRef("avx2_do_last_block")) } -// Definitions for AVX2 version +func done_hash() { + Label("done_hash") + VZEROUPPER() + RET() +} // addm (mem), reg // - Add reg to mem using reg-mem add and store @@ -586,489 +647,6 @@ func doRoundN3(disp int, a, b, c, d, e, f, g, h, old_h GPPhysical) { ADDL(y3, h) // h = t1 + S0 + MAJ } -// Definitions for sha-ni version -// -// The sha-ni implementation uses Intel(R) SHA extensions SHA256RNDS2, SHA256MSG1, SHA256MSG2 -// It also reuses portions of the flip_mask (half) and K256 table (stride 32) from the avx2 version -// -// Reference -// S. Gulley, et al, "New Instructions Supporting the Secure Hash -// Algorithm on Intel® Architecture Processors", July 2013 -// https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sha-extensions.html -// - -var ( - digestPtr GPPhysical = RDI // input/output, base pointer to digest hash vector H0, H1, ..., H7 - dataPtr = RSI // input, base pointer to first input data block - numBytes = RDX // input, number of input bytes to be processed - sha256Constants = RAX // round contents from K256 table, indexed by round number x 32 - msg VecPhysical = X0 // input data - state0 = X1 // round intermediates and outputs - state1 = X2 - m0 = X3 // m0, m1,... m4 -- round message temps - m1 = X4 - m2 = X5 - m3 = X6 - m4 = X7 - shufMask = X8 // input data endian conversion control mask - abefSave = X9 // digest hash vector inter-block buffer abef - cdghSave = X10 // digest hash vector inter-block buffer cdgh -) - -// nop instead of final SHA256MSG1 for first and last few rounds -func nop(m, a VecPhysical) { -} - -// final SHA256MSG1 for middle rounds that require it -func sha256msg1(m, a VecPhysical) { - SHA256MSG1(m, a) -} - -// msg copy for all but rounds 12-15 -func vmov(a, b VecPhysical) { - VMOVDQA(a, b) -} - -// reverse copy for rounds 12-15 -func vmovrev(a, b VecPhysical) { - VMOVDQA(b, a) -} - -type VecFunc func(a, b VecPhysical) - -// sha rounds 0 to 11 -// -// identical with the exception of the final msg op -// which is replaced with a nop for rounds where it is not needed -// refer to Gulley, et al for more information -func rounds0to11(m, a VecPhysical, c int, sha256msg1 VecFunc) { - VMOVDQU(Mem{Base: dataPtr}.Offset(c*16), msg) - PSHUFB(shufMask, msg) - VMOVDQA(msg, m) - PADDD(Mem{Base: sha256Constants}.Offset(c*32), msg) - SHA256RNDS2(msg, state0, state1) - PSHUFD(U8(0x0e), msg, msg) - SHA256RNDS2(msg, state1, state0) - sha256msg1(m, a) -} - -// sha rounds 12 to 59 -// -// identical with the exception of the final msg op -// and the reverse copy(m,msg) in round 12 which is required -// after the last data load -// refer to Gulley, et al for more information -func rounds12to59(m VecPhysical, c int, a, t VecPhysical, sha256msg1, movop VecFunc) { - movop(m, msg) - PADDD(Mem{Base: sha256Constants}.Offset(c*32), msg) - SHA256RNDS2(msg, state0, state1) - VMOVDQA(m, m4) - PALIGNR(Imm(4), a, m4) - PADDD(m4, t) - SHA256MSG2(m, t) - PSHUFD(Imm(0x0e), msg, msg) - SHA256RNDS2(msg, state1, state0) - sha256msg1(m, a) -} - -func block() { - Implement("block") - AllocLocal(536) - - checkArchFlags() - sha256() - avx2() - sha_ni() -} - -func checkArchFlags() { - CMPB(Mem{Symbol: Symbol{Name: "·useSHA"}, Base: StaticBase}, Imm(1)) - JE(LabelRef("sha_ni")) - CMPB(Mem{Symbol: Symbol{Name: "·useAVX2"}, Base: StaticBase}, Imm(1)) - JE(LabelRef("avx2")) -} - -func sha256() { - Load(Param("p").Base(), RSI) - Load(Param("p").Len(), RDX) - SHRQ(Imm(6), RDX) - SHLQ(Imm(6), RDX) - - // Return if p is empty - LEAQ(Mem{Base: RSI, Index: RDX, Scale: 1}, RDI) - MOVQ(RDI, Mem{Base: SP}.Offset(256)) - CMPQ(RSI, RDI) - JEQ(LabelRef("end")) - - BP := Mem{Base: BP} - Load(Param("dig"), RBP) - MOVL(BP.Offset(0*4), R8L) // a = H0 - MOVL(BP.Offset(1*4), R9L) // b = H1 - MOVL(BP.Offset(2*4), R10L) // c = H2 - MOVL(BP.Offset(3*4), R11L) // d = H3 - MOVL(BP.Offset(4*4), R12L) // e = H4 - MOVL(BP.Offset(5*4), R13L) // f = H5 - MOVL(BP.Offset(6*4), R14L) // g = H6 - MOVL(BP.Offset(7*4), R15L) // h = H7 - - loop() - end() -} - -func rotateRight(slice *[]GPPhysical) []GPPhysical { - n := len(*slice) - new := make([]GPPhysical, n) - for i, reg := range *slice { - new[(i+1)%n] = reg - } - return new -} - -func loop() { - Label("loop") - MOVQ(RSP, RBP) - - regs := []GPPhysical{R8L, R9L, R10L, R11L, R12L, R13L, R14L, R15L} - n := len(_K) - - for i := 0; i < 16; i++ { - sha256Round0(i, _K[i], regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]) - regs = rotateRight(®s) - } - - for i := 16; i < n; i++ { - sha256Round1(i, _K[i], regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]) - regs = rotateRight(®s) - } - - Load(Param("dig"), RBP) - BP := Mem{Base: BP} - ADDL(BP.Offset(0*4), R8L) // H0 = a + H0 - MOVL(R8L, BP.Offset(0*4)) - ADDL(BP.Offset(1*4), R9L) // H1 = b + H1 - MOVL(R9L, BP.Offset(1*4)) - ADDL(BP.Offset(2*4), R10L) // H2 = c + H2 - MOVL(R10L, BP.Offset(2*4)) - ADDL(BP.Offset(3*4), R11L) // H3 = d + H3 - MOVL(R11L, BP.Offset(3*4)) - ADDL(BP.Offset(4*4), R12L) // H4 = e + H4 - MOVL(R12L, BP.Offset(4*4)) - ADDL(BP.Offset(5*4), R13L) // H5 = f + H5 - MOVL(R13L, BP.Offset(5*4)) - ADDL(BP.Offset(6*4), R14L) // H6 = g + H6 - MOVL(R14L, BP.Offset(6*4)) - ADDL(BP.Offset(7*4), R15L) // H7 = h + H7 - MOVL(R15L, BP.Offset(7*4)) - - ADDQ(Imm(64), RSI) - CMPQ(RSI, Mem{Base: SP}.Offset(256)) - JB(LabelRef("loop")) -} - -func end() { - Label("end") - RET() -} - -func avx2() { - Label("avx2") - Load(Param("dig"), CTX) // d.h[8] - Load(Param("p").Base(), INP) - Load(Param("p").Len(), NUM_BYTES) - - LEAQ(Mem{Base: INP, Index: NUM_BYTES, Scale: 1, Disp: -64}, NUM_BYTES) // Pointer to the last block - MOVQ(NUM_BYTES, Mem{Base: SP}.Offset(_INP_END)) - - CMPQ(NUM_BYTES, INP) - JE(LabelRef("avx2_only_one_block")) - - Comment("Load initial digest") - CTX := Mem{Base: CTX} - MOVL(CTX.Offset(0), a) // a = H0 - MOVL(CTX.Offset(4), b) // b = H1 - MOVL(CTX.Offset(8), c) // c = H2 - MOVL(CTX.Offset(12), d) // d = H3 - MOVL(CTX.Offset(16), e) // e = H4 - MOVL(CTX.Offset(20), f) // f = H5 - MOVL(CTX.Offset(24), g) // g = H6 - MOVL(CTX.Offset(28), h) // h = H7 - - avx2_loop0() - avx2_last_block_enter() - avx2_loop1() - avx2_loop2() - avx2_loop3() - avx2_do_last_block() - avx2_only_one_block() - done_hash() -} - -func avx2_loop0() { - Label("avx2_loop0") - Comment("at each iteration works with one block (512 bit)") - VMOVDQU(Mem{Base: INP}.Offset(0*32), XTMP0) - VMOVDQU(Mem{Base: INP}.Offset(1*32), XTMP1) - VMOVDQU(Mem{Base: INP}.Offset(2*32), XTMP2) - VMOVDQU(Mem{Base: INP}.Offset(3*32), XTMP3) - - flip_mask := flip_mask_DATA() - - VMOVDQU(flip_mask, BYTE_FLIP_MASK) - - Comment("Apply Byte Flip Mask: LE -> BE") - VPSHUFB(BYTE_FLIP_MASK, XTMP0, XTMP0) - VPSHUFB(BYTE_FLIP_MASK, XTMP1, XTMP1) - VPSHUFB(BYTE_FLIP_MASK, XTMP2, XTMP2) - VPSHUFB(BYTE_FLIP_MASK, XTMP3, XTMP3) - - Comment("Transpose data into high/low parts") - VPERM2I128(Imm(0x20), XTMP2, XTMP0, XDWORD0) // w3, w2, w1, w0 - VPERM2I128(Imm(0x31), XTMP2, XTMP0, XDWORD1) // w7, w6, w5, w4 - VPERM2I128(Imm(0x20), XTMP3, XTMP1, XDWORD2) // w11, w10, w9, w8 - VPERM2I128(Imm(0x31), XTMP3, XTMP1, XDWORD3) // w15, w14, w13, w12 - - K256 := K256_DATA() - LEAQ(K256, TBL) // Loading address of table with round-specific constants -} - -func avx2_last_block_enter() { - Label("avx2_last_block_enter") - ADDQ(Imm(64), INP) - MOVQ(INP, Mem{Base: SP}.Offset(_INP)) - XORQ(SRND, SRND) -} - -// for w0 - w47 -func avx2_loop1() { - Label("avx2_loop1") - - Comment("Do 4 rounds and scheduling") - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((0 * 32)), XDWORD0, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+0*32)) - roundAndSchedN0(_XFER+0*32, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) - roundAndSchedN1(_XFER+0*32, h, a, b, c, d, e, f, g, XDWORD0, XDWORD1, XDWORD2, XDWORD3) - roundAndSchedN2(_XFER+0*32, g, h, a, b, c, d, e, f, XDWORD0, XDWORD1, XDWORD2, XDWORD3) - roundAndSchedN3(_XFER+0*32, f, g, h, a, b, c, d, e, XDWORD0, XDWORD1, XDWORD2, XDWORD3) - - Comment("Do 4 rounds and scheduling") - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(1*32), XDWORD1, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+1*32)) - roundAndSchedN0(_XFER+1*32, e, f, g, h, a, b, c, d, XDWORD1, XDWORD2, XDWORD3, XDWORD0) - roundAndSchedN1(_XFER+1*32, d, e, f, g, h, a, b, c, XDWORD1, XDWORD2, XDWORD3, XDWORD0) - roundAndSchedN2(_XFER+1*32, c, d, e, f, g, h, a, b, XDWORD1, XDWORD2, XDWORD3, XDWORD0) - roundAndSchedN3(_XFER+1*32, b, c, d, e, f, g, h, a, XDWORD1, XDWORD2, XDWORD3, XDWORD0) - - Comment("Do 4 rounds and scheduling") - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((2 * 32)), XDWORD2, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+2*32)) - roundAndSchedN0(_XFER+2*32, a, b, c, d, e, f, g, h, XDWORD2, XDWORD3, XDWORD0, XDWORD1) - roundAndSchedN1(_XFER+2*32, h, a, b, c, d, e, f, g, XDWORD2, XDWORD3, XDWORD0, XDWORD1) - roundAndSchedN2(_XFER+2*32, g, h, a, b, c, d, e, f, XDWORD2, XDWORD3, XDWORD0, XDWORD1) - roundAndSchedN3(_XFER+2*32, f, g, h, a, b, c, d, e, XDWORD2, XDWORD3, XDWORD0, XDWORD1) - - Comment("Do 4 rounds and scheduling") - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset((3 * 32)), XDWORD3, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+3*32)) - roundAndSchedN0(_XFER+3*32, e, f, g, h, a, b, c, d, XDWORD3, XDWORD0, XDWORD1, XDWORD2) - roundAndSchedN1(_XFER+3*32, d, e, f, g, h, a, b, c, XDWORD3, XDWORD0, XDWORD1, XDWORD2) - roundAndSchedN2(_XFER+3*32, c, d, e, f, g, h, a, b, XDWORD3, XDWORD0, XDWORD1, XDWORD2) - roundAndSchedN3(_XFER+3*32, b, c, d, e, f, g, h, a, XDWORD3, XDWORD0, XDWORD1, XDWORD2) - - ADDQ(Imm(4*32), SRND) - CMPQ(SRND, U32(3*4*32)) - JB(LabelRef("avx2_loop1")) -} - -// w48 - w63 processed with no scheduling (last 16 rounds) -func avx2_loop2() { - Label("avx2_loop2") - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(0*32), XDWORD0, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+0*32)) - doRoundN0(_XFER+0*32, a, b, c, d, e, f, g, h, h) - doRoundN1(_XFER+0*32, h, a, b, c, d, e, f, g, h) - doRoundN2(_XFER+0*32, g, h, a, b, c, d, e, f, g) - doRoundN3(_XFER+0*32, f, g, h, a, b, c, d, e, f) - - VPADDD(Mem{Base: TBL, Scale: 1, Index: SRND}.Offset(1*32), XDWORD1, XFER) - VMOVDQU(XFER, Mem{Base: SP, Scale: 1, Index: SRND}.Offset(_XFER+1*32)) - doRoundN0(_XFER+1*32, e, f, g, h, a, b, c, d, e) - doRoundN1(_XFER+1*32, d, e, f, g, h, a, b, c, d) - doRoundN2(_XFER+1*32, c, d, e, f, g, h, a, b, c) - doRoundN3(_XFER+1*32, b, c, d, e, f, g, h, a, b) - - ADDQ(Imm(2*32), SRND) - - VMOVDQU(XDWORD2, XDWORD0) - VMOVDQU(XDWORD3, XDWORD1) - - CMPQ(SRND, U32(4*4*32)) - JB(LabelRef("avx2_loop2")) - - Load(Param("dig"), CTX) // d.h[8] - MOVQ(Mem{Base: SP}.Offset(_INP), INP) - - registers := []GPPhysical{a, b, c, d, e, f, g, h} - for i, reg := range registers { - addm(Mem{Base: CTX}.Offset(i*4), reg) - } - - CMPQ(Mem{Base: SP}.Offset(_INP_END), INP) - JB(LabelRef("done_hash")) - - XORQ(SRND, SRND) -} - -// Do second block using previously scheduled results -func avx2_loop3() { - Label("avx2_loop3") - doRoundN0(_XFER+0*32+16, a, b, c, d, e, f, g, h, a) - doRoundN1(_XFER+0*32+16, h, a, b, c, d, e, f, g, h) - doRoundN2(_XFER+0*32+16, g, h, a, b, c, d, e, f, g) - doRoundN3(_XFER+0*32+16, f, g, h, a, b, c, d, e, f) - - doRoundN0(_XFER+1*32+16, e, f, g, h, a, b, c, d, e) - doRoundN1(_XFER+1*32+16, d, e, f, g, h, a, b, c, d) - doRoundN2(_XFER+1*32+16, c, d, e, f, g, h, a, b, c) - doRoundN3(_XFER+1*32+16, b, c, d, e, f, g, h, a, b) - - ADDQ(Imm(2*32), SRND) - CMPQ(SRND, U32(4*4*32)) - JB(LabelRef("avx2_loop3")) - - Load(Param("dig"), CTX) // d.h[8] - MOVQ(Mem{Base: SP}.Offset(_INP), INP) - ADDQ(Imm(64), INP) - - registers := []GPPhysical{a, b, c, d, e, f, g, h} - for i, reg := range registers { - addm(Mem{Base: CTX}.Offset(i*4), reg) - } - - CMPQ(Mem{Base: SP}.Offset(_INP_END), INP) - JA(LabelRef("avx2_loop0")) - JB(LabelRef("done_hash")) -} - -func avx2_do_last_block() { - Label("avx2_do_last_block") - VMOVDQU(Mem{Base: INP}.Offset(0), XWORD0) - VMOVDQU(Mem{Base: INP}.Offset(16), XWORD1) - VMOVDQU(Mem{Base: INP}.Offset(32), XWORD2) - VMOVDQU(Mem{Base: INP}.Offset(48), XWORD3) - - flip_mask := flip_mask_DATA() - VMOVDQU(flip_mask, BYTE_FLIP_MASK) - - VPSHUFB(X_BYTE_FLIP_MASK, XWORD0, XWORD0) - VPSHUFB(X_BYTE_FLIP_MASK, XWORD1, XWORD1) - VPSHUFB(X_BYTE_FLIP_MASK, XWORD2, XWORD2) - VPSHUFB(X_BYTE_FLIP_MASK, XWORD3, XWORD3) - - K256 := K256_DATA() - LEAQ(K256, TBL) - - JMP(LabelRef("avx2_last_block_enter")) -} - -// Load initial digest -func avx2_only_one_block() { - Label("avx2_only_one_block") - registers := []GPPhysical{a, b, c, d, e, f, g, h} - for i, reg := range registers { - MOVL(Mem{Base: CTX}.Offset(i*4), reg) - } - JMP(LabelRef("avx2_do_last_block")) -} - -func done_hash() { - Label("done_hash") - VZEROUPPER() - RET() -} - -func sha_ni() { - Label("sha_ni") - Load(Param("dig"), digestPtr) // init digest hash vector H0, H1,..., H7 pointer - Load(Param("p").Base(), dataPtr) // init input data base pointer - Load(Param("p").Len(), numBytes) // get number of input bytes to hash - SHRQ(Imm(6), numBytes) // force modulo 64 input buffer length - SHLQ(Imm(6), numBytes) - CMPQ(numBytes, Imm(0)) // exit early for zero-length input buffer - JEQ(LabelRef("done")) - ADDQ(dataPtr, numBytes) // point numBytes to end of input buffer - VMOVDQU(Mem{Base: digestPtr}.Offset(0*16), state0) // load initial hash values and reorder - VMOVDQU(Mem{Base: digestPtr}.Offset(1*16), state1) // DCBA, HGFE -> ABEF, CDGH - PSHUFD(Imm(0xb1), state0, state0) // CDAB - PSHUFD(Imm(0x1b), state1, state1) // EFGH - VMOVDQA(state0, m4) - PALIGNR(Imm(8), state1, state0) // ABEF - PBLENDW(Imm(0xf0), m4, state1) // CDGH - flip_mask := flip_mask_DATA() - VMOVDQA(flip_mask, shufMask) - LEAQ(K256_DATA(), sha256Constants) - - roundLoop() - done() -} - -func roundLoop() { - Label("roundLoop") - Comment("save hash values for addition after rounds") - VMOVDQA(state0, abefSave) - VMOVDQA(state1, cdghSave) - - Comment("do rounds 0-59") - rounds0to11(m0, nil, 0, nop) // 0-3 - rounds0to11(m1, m0, 1, sha256msg1) // 4-7 - rounds0to11(m2, m1, 2, sha256msg1) // 8-11 - VMOVDQU(Mem{Base: dataPtr}.Offset(3*16), msg) - PSHUFB(shufMask, msg) - rounds12to59(m3, 3, m2, m0, sha256msg1, vmovrev) // 12-15 - rounds12to59(m0, 4, m3, m1, sha256msg1, vmov) // 16-19 - rounds12to59(m1, 5, m0, m2, sha256msg1, vmov) // 20-23 - rounds12to59(m2, 6, m1, m3, sha256msg1, vmov) // 24-27 - rounds12to59(m3, 7, m2, m0, sha256msg1, vmov) // 28-31 - rounds12to59(m0, 8, m3, m1, sha256msg1, vmov) // 32-35 - rounds12to59(m1, 9, m0, m2, sha256msg1, vmov) // 36-39 - rounds12to59(m2, 10, m1, m3, sha256msg1, vmov) // 40-43 - rounds12to59(m3, 11, m2, m0, sha256msg1, vmov) // 44-47 - rounds12to59(m0, 12, m3, m1, sha256msg1, vmov) // 48-51 - rounds12to59(m1, 13, m0, m2, nop, vmov) // 52-55 - rounds12to59(m2, 14, m1, m3, nop, vmov) // 56-59 - - Comment("do rounds 60-63") - VMOVDQA(m3, msg) - PADDD(Mem{Base: sha256Constants}.Offset(15*32), msg) - SHA256RNDS2(msg, state0, state1) - PSHUFD(Imm(0x0e), msg, msg) - SHA256RNDS2(msg, state1, state0) - - Comment("add current hash values with previously saved") - PADDD(abefSave, state0) - PADDD(cdghSave, state1) - - Comment("advance data pointer; loop until buffer empty") - ADDQ(Imm(64), dataPtr) - CMPQ(numBytes, dataPtr) - JNE(LabelRef("roundLoop")) - - Comment("write hash values back in the correct order") - PSHUFD(Imm(0x1b), state0, state0) - PSHUFD(Imm(0xb1), state1, state1) - VMOVDQA(state0, m4) - PBLENDW(Imm(0xf0), state1, state0) - PALIGNR(Imm(8), m4, state1) - VMOVDQU(state0, Mem{Base: digestPtr}.Offset(0*16)) - VMOVDQU(state1, Mem{Base: digestPtr}.Offset(1*16)) -} - -func done() { - Label("done") - RET() -} - -/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/ - // Pointers for memoizing Data section symbols var flip_maskPtr, shuff_00BAPtr, shuff_DC00Ptr, K256Ptr *Mem @@ -1120,73 +698,6 @@ func shuff_DC00_DATA() Mem { return shuff_DC00 } -var _K = []uint32{ - 0x428a2f98, - 0x71374491, - 0xb5c0fbcf, - 0xe9b5dba5, - 0x3956c25b, - 0x59f111f1, - 0x923f82a4, - 0xab1c5ed5, - 0xd807aa98, - 0x12835b01, - 0x243185be, - 0x550c7dc3, - 0x72be5d74, - 0x80deb1fe, - 0x9bdc06a7, - 0xc19bf174, - 0xe49b69c1, - 0xefbe4786, - 0x0fc19dc6, - 0x240ca1cc, - 0x2de92c6f, - 0x4a7484aa, - 0x5cb0a9dc, - 0x76f988da, - 0x983e5152, - 0xa831c66d, - 0xb00327c8, - 0xbf597fc7, - 0xc6e00bf3, - 0xd5a79147, - 0x06ca6351, - 0x14292967, - 0x27b70a85, - 0x2e1b2138, - 0x4d2c6dfc, - 0x53380d13, - 0x650a7354, - 0x766a0abb, - 0x81c2c92e, - 0x92722c85, - 0xa2bfe8a1, - 0xa81a664b, - 0xc24b8b70, - 0xc76c51a3, - 0xd192e819, - 0xd6990624, - 0xf40e3585, - 0x106aa070, - 0x19a4c116, - 0x1e376c08, - 0x2748774c, - 0x34b0bcb5, - 0x391c0cb3, - 0x4ed8aa4a, - 0x5b9cca4f, - 0x682e6ff3, - 0x748f82ee, - 0x78a5636f, - 0x84c87814, - 0x8cc70208, - 0x90befffa, - 0xa4506ceb, - 0xbef9a3f7, - 0xc67178f2, -} - // Round specific constants func K256_DATA() Mem { if K256Ptr != nil { diff --git a/crypto/internal/fips140/sha256/_asm/sha256block_amd64_shani.go b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_shani.go new file mode 100644 index 00000000000..423e86206fa --- /dev/null +++ b/crypto/internal/fips140/sha256/_asm/sha256block_amd64_shani.go @@ -0,0 +1,174 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +// The sha-ni implementation uses Intel(R) SHA extensions SHA256RNDS2, SHA256MSG1, SHA256MSG2 +// It also reuses portions of the flip_mask (half) and K256 table (stride 32) from the avx2 version +// +// Reference +// S. Gulley, et al, "New Instructions Supporting the Secure Hash +// Algorithm on Intel® Architecture Processors", July 2013 +// https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sha-extensions.html + +func blockSHANI() { + Implement("blockSHANI") + Load(Param("dig"), digestPtr) // init digest hash vector H0, H1,..., H7 pointer + Load(Param("p").Base(), dataPtr) // init input data base pointer + Load(Param("p").Len(), numBytes) // get number of input bytes to hash + SHRQ(Imm(6), numBytes) // force modulo 64 input buffer length + SHLQ(Imm(6), numBytes) + CMPQ(numBytes, Imm(0)) // exit early for zero-length input buffer + JEQ(LabelRef("done")) + ADDQ(dataPtr, numBytes) // point numBytes to end of input buffer + VMOVDQU(Mem{Base: digestPtr}.Offset(0*16), state0) // load initial hash values and reorder + VMOVDQU(Mem{Base: digestPtr}.Offset(1*16), state1) // DCBA, HGFE -> ABEF, CDGH + PSHUFD(Imm(0xb1), state0, state0) // CDAB + PSHUFD(Imm(0x1b), state1, state1) // EFGH + VMOVDQA(state0, m4) + PALIGNR(Imm(8), state1, state0) // ABEF + PBLENDW(Imm(0xf0), m4, state1) // CDGH + flip_mask := flip_mask_DATA() + VMOVDQA(flip_mask, shufMask) + LEAQ(K256_DATA(), sha256Constants) + + roundLoop() + done() +} + +func roundLoop() { + Label("roundLoop") + Comment("save hash values for addition after rounds") + VMOVDQA(state0, abefSave) + VMOVDQA(state1, cdghSave) + + Comment("do rounds 0-59") + rounds0to11(m0, nil, 0, nop) // 0-3 + rounds0to11(m1, m0, 1, sha256msg1) // 4-7 + rounds0to11(m2, m1, 2, sha256msg1) // 8-11 + VMOVDQU(Mem{Base: dataPtr}.Offset(3*16), msg) + PSHUFB(shufMask, msg) + rounds12to59(m3, 3, m2, m0, sha256msg1, vmovrev) // 12-15 + rounds12to59(m0, 4, m3, m1, sha256msg1, vmov) // 16-19 + rounds12to59(m1, 5, m0, m2, sha256msg1, vmov) // 20-23 + rounds12to59(m2, 6, m1, m3, sha256msg1, vmov) // 24-27 + rounds12to59(m3, 7, m2, m0, sha256msg1, vmov) // 28-31 + rounds12to59(m0, 8, m3, m1, sha256msg1, vmov) // 32-35 + rounds12to59(m1, 9, m0, m2, sha256msg1, vmov) // 36-39 + rounds12to59(m2, 10, m1, m3, sha256msg1, vmov) // 40-43 + rounds12to59(m3, 11, m2, m0, sha256msg1, vmov) // 44-47 + rounds12to59(m0, 12, m3, m1, sha256msg1, vmov) // 48-51 + rounds12to59(m1, 13, m0, m2, nop, vmov) // 52-55 + rounds12to59(m2, 14, m1, m3, nop, vmov) // 56-59 + + Comment("do rounds 60-63") + VMOVDQA(m3, msg) + PADDD(Mem{Base: sha256Constants}.Offset(15*32), msg) + SHA256RNDS2(msg, state0, state1) + PSHUFD(Imm(0x0e), msg, msg) + SHA256RNDS2(msg, state1, state0) + + Comment("add current hash values with previously saved") + PADDD(abefSave, state0) + PADDD(cdghSave, state1) + + Comment("advance data pointer; loop until buffer empty") + ADDQ(Imm(64), dataPtr) + CMPQ(numBytes, dataPtr) + JNE(LabelRef("roundLoop")) + + Comment("write hash values back in the correct order") + PSHUFD(Imm(0x1b), state0, state0) + PSHUFD(Imm(0xb1), state1, state1) + VMOVDQA(state0, m4) + PBLENDW(Imm(0xf0), state1, state0) + PALIGNR(Imm(8), m4, state1) + VMOVDQU(state0, Mem{Base: digestPtr}.Offset(0*16)) + VMOVDQU(state1, Mem{Base: digestPtr}.Offset(1*16)) +} + +func done() { + Label("done") + RET() +} + +var ( + digestPtr GPPhysical = RDI // input/output, base pointer to digest hash vector H0, H1, ..., H7 + dataPtr = RSI // input, base pointer to first input data block + numBytes = RDX // input, number of input bytes to be processed + sha256Constants = RAX // round contents from K256 table, indexed by round number x 32 + msg VecPhysical = X0 // input data + state0 = X1 // round intermediates and outputs + state1 = X2 + m0 = X3 // m0, m1,... m4 -- round message temps + m1 = X4 + m2 = X5 + m3 = X6 + m4 = X7 + shufMask = X8 // input data endian conversion control mask + abefSave = X9 // digest hash vector inter-block buffer abef + cdghSave = X10 // digest hash vector inter-block buffer cdgh +) + +// nop instead of final SHA256MSG1 for first and last few rounds +func nop(m, a VecPhysical) { +} + +// final SHA256MSG1 for middle rounds that require it +func sha256msg1(m, a VecPhysical) { + SHA256MSG1(m, a) +} + +// msg copy for all but rounds 12-15 +func vmov(a, b VecPhysical) { + VMOVDQA(a, b) +} + +// reverse copy for rounds 12-15 +func vmovrev(a, b VecPhysical) { + VMOVDQA(b, a) +} + +type VecFunc func(a, b VecPhysical) + +// sha rounds 0 to 11 +// +// identical with the exception of the final msg op +// which is replaced with a nop for rounds where it is not needed +// refer to Gulley, et al for more information +func rounds0to11(m, a VecPhysical, c int, sha256msg1 VecFunc) { + VMOVDQU(Mem{Base: dataPtr}.Offset(c*16), msg) + PSHUFB(shufMask, msg) + VMOVDQA(msg, m) + PADDD(Mem{Base: sha256Constants}.Offset(c*32), msg) + SHA256RNDS2(msg, state0, state1) + PSHUFD(U8(0x0e), msg, msg) + SHA256RNDS2(msg, state1, state0) + sha256msg1(m, a) +} + +// sha rounds 12 to 59 +// +// identical with the exception of the final msg op +// and the reverse copy(m,msg) in round 12 which is required +// after the last data load +// refer to Gulley, et al for more information +func rounds12to59(m VecPhysical, c int, a, t VecPhysical, sha256msg1, movop VecFunc) { + movop(m, msg) + PADDD(Mem{Base: sha256Constants}.Offset(c*32), msg) + SHA256RNDS2(msg, state0, state1) + VMOVDQA(m, m4) + PALIGNR(Imm(4), a, m4) + PADDD(m4, t) + SHA256MSG2(m, t) + PSHUFD(Imm(0x0e), msg, msg) + SHA256RNDS2(msg, state1, state0) + sha256msg1(m, a) +} diff --git a/crypto/internal/fips140/sha256/cast.go b/crypto/internal/fips140/sha256/cast.go new file mode 100644 index 00000000000..b7d142a9a6f --- /dev/null +++ b/crypto/internal/fips140/sha256/cast.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha256 + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + fips140.CAST("SHA2-256", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0x5d, 0xfb, 0xab, 0xee, 0xdf, 0x31, 0x8b, 0xf3, + 0x3c, 0x09, 0x27, 0xc4, 0x3d, 0x76, 0x30, 0xf5, + 0x1b, 0x82, 0xf3, 0x51, 0x74, 0x03, 0x01, 0x35, + 0x4f, 0xa3, 0xd7, 0xfc, 0x51, 0xf0, 0x13, 0x2e, + } + h := New() + h.Write(input) + if got := h.Sum(nil); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/sha256/sha256.go b/crypto/internal/fips140/sha256/sha256.go new file mode 100644 index 00000000000..acbf7caee5a --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256.go @@ -0,0 +1,248 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha256 implements the SHA-224 and SHA-256 hash algorithms as defined +// in FIPS 180-4. +package sha256 + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/hash" +) + +// The size of a SHA-256 checksum in bytes. +const size = 32 + +// The size of a SHA-224 checksum in bytes. +const size224 = 28 + +// The block size of SHA-256 and SHA-224 in bytes. +const blockSize = 64 + +// The maximum number of bytes that can be passed to block(). The limit exists +// because implementations that rely on assembly routines are not preemptible. +const maxAsmIters = 1024 +const maxAsmSize = blockSize * maxAsmIters // 64KiB + +const ( + chunk = 64 + init0 = 0x6A09E667 + init1 = 0xBB67AE85 + init2 = 0x3C6EF372 + init3 = 0xA54FF53A + init4 = 0x510E527F + init5 = 0x9B05688C + init6 = 0x1F83D9AB + init7 = 0x5BE0CD19 + init0_224 = 0xC1059ED8 + init1_224 = 0x367CD507 + init2_224 = 0x3070DD17 + init3_224 = 0xF70E5939 + init4_224 = 0xFFC00B31 + init5_224 = 0x68581511 + init6_224 = 0x64F98FA7 + init7_224 = 0xBEFA4FA4 +) + +// Digest is a SHA-224 or SHA-256 [hash.Hash] implementation. +type Digest struct { + h [8]uint32 + x [chunk]byte + nx int + len uint64 + is224 bool // mark if this digest is SHA-224 +} + +const ( + magic224 = "sha\x02" + magic256 = "sha\x03" + marshaledSize = len(magic256) + 8*4 + chunk + 8 +) + +func (d *Digest) MarshalBinary() ([]byte, error) { + return d.AppendBinary(make([]byte, 0, marshaledSize)) +} + +func (d *Digest) AppendBinary(b []byte) ([]byte, error) { + if d.is224 { + b = append(b, magic224...) + } else { + b = append(b, magic256...) + } + b = byteorder.BEAppendUint32(b, d.h[0]) + b = byteorder.BEAppendUint32(b, d.h[1]) + b = byteorder.BEAppendUint32(b, d.h[2]) + b = byteorder.BEAppendUint32(b, d.h[3]) + b = byteorder.BEAppendUint32(b, d.h[4]) + b = byteorder.BEAppendUint32(b, d.h[5]) + b = byteorder.BEAppendUint32(b, d.h[6]) + b = byteorder.BEAppendUint32(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-d.nx)...) + b = byteorder.BEAppendUint64(b, d.len) + return b, nil +} + +func (d *Digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) { + return errors.New("crypto/sha256: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/sha256: invalid hash state size") + } + b = b[len(magic224):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b, d.h[5] = consumeUint32(b) + b, d.h[6] = consumeUint32(b) + b, d.h[7] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % chunk) + return nil +} + +func consumeUint64(b []byte) ([]byte, uint64) { + return b[8:], byteorder.BEUint64(b) +} + +func consumeUint32(b []byte) ([]byte, uint32) { + return b[4:], byteorder.BEUint32(b) +} + +func (d *Digest) Clone() (hash.Cloner, error) { + r := *d + return &r, nil +} + +func (d *Digest) Reset() { + if !d.is224 { + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.h[5] = init5 + d.h[6] = init6 + d.h[7] = init7 + } else { + d.h[0] = init0_224 + d.h[1] = init1_224 + d.h[2] = init2_224 + d.h[3] = init3_224 + d.h[4] = init4_224 + d.h[5] = init5_224 + d.h[6] = init6_224 + d.h[7] = init7_224 + } + d.nx = 0 + d.len = 0 +} + +// New returns a new Digest computing the SHA-256 hash. +func New() *Digest { + d := new(Digest) + d.Reset() + return d +} + +// New224 returns a new Digest computing the SHA-224 hash. +func New224() *Digest { + d := new(Digest) + d.is224 = true + d.Reset() + return d +} + +func (d *Digest) Size() int { + if !d.is224 { + return size + } + return size224 +} + +func (d *Digest) BlockSize() int { return blockSize } + +func (d *Digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + for n > maxAsmSize { + block(d, p[:maxAsmSize]) + p = p[maxAsmSize:] + n -= maxAsmSize + } + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *Digest) Sum(in []byte) []byte { + fips140.RecordApproved() + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + if d0.is224 { + return append(in, hash[:size224]...) + } + return append(in, hash[:]...) +} + +func (d *Digest) checkSum() [size]byte { + len := d.len + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + var tmp [64 + 8]byte // padding + length buffer + tmp[0] = 0x80 + var t uint64 + if len%64 < 56 { + t = 56 - len%64 + } else { + t = 64 + 56 - len%64 + } + + // Length in bits. + len <<= 3 + padlen := tmp[:t+8] + byteorder.BEPutUint64(padlen[t+0:], len) + d.Write(padlen) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [size]byte + + byteorder.BEPutUint32(digest[0:], d.h[0]) + byteorder.BEPutUint32(digest[4:], d.h[1]) + byteorder.BEPutUint32(digest[8:], d.h[2]) + byteorder.BEPutUint32(digest[12:], d.h[3]) + byteorder.BEPutUint32(digest[16:], d.h[4]) + byteorder.BEPutUint32(digest[20:], d.h[5]) + byteorder.BEPutUint32(digest[24:], d.h[6]) + if !d.is224 { + byteorder.BEPutUint32(digest[28:], d.h[7]) + } + + return digest +} diff --git a/crypto/sha256/sha256block.go b/crypto/internal/fips140/sha256/sha256block.go similarity index 97% rename from crypto/sha256/sha256block.go rename to crypto/internal/fips140/sha256/sha256block.go index bd2f9da93ce..55a400e2502 100644 --- a/crypto/sha256/sha256block.go +++ b/crypto/internal/fips140/sha256/sha256block.go @@ -10,7 +10,7 @@ package sha256 import "math/bits" -var _K = []uint32{ +var _K = [...]uint32{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, @@ -77,7 +77,7 @@ var _K = []uint32{ 0xc67178f2, } -func blockGeneric(dig *digest, p []byte) { +func blockGeneric(dig *Digest, p []byte) { var w [64]uint32 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] for len(p) >= chunk { diff --git a/crypto/sha256/sha256block_386.s b/crypto/internal/fips140/sha256/sha256block_386.s similarity index 100% rename from crypto/sha256/sha256block_386.s rename to crypto/internal/fips140/sha256/sha256block_386.s diff --git a/crypto/internal/fips140/sha256/sha256block_amd64.go b/crypto/internal/fips140/sha256/sha256block_amd64.go new file mode 100644 index 00000000000..5d2c46f5336 --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256block_amd64.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha256 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useAVX2 = cpu.X86HasAVX && cpu.X86HasAVX2 && cpu.X86HasBMI2 +var useSHANI = cpu.X86HasAVX && cpu.X86HasSHA && cpu.X86HasSSE41 && cpu.X86HasSSSE3 + +func init() { + impl.Register("sha256", "AVX2", &useAVX2) + impl.Register("sha256", "SHA-NI", &useSHANI) +} + +//go:noescape +func blockAVX2(dig *Digest, p []byte) + +//go:noescape +func blockSHANI(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useSHANI { + blockSHANI(dig, p) + } else if useAVX2 { + blockAVX2(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/internal/fips140/sha256/sha256block_amd64.s b/crypto/internal/fips140/sha256/sha256block_amd64.s new file mode 100644 index 00000000000..d5ab42c819e --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256block_amd64.s @@ -0,0 +1,1486 @@ +// Code generated by command: go run sha256block_amd64_asm.go -out ../sha256block_amd64.s. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +// func blockAVX2(dig *Digest, p []byte) +// Requires: AVX, AVX2, BMI2 +TEXT ·blockAVX2(SB), $536-32 + MOVQ dig+0(FP), SI + MOVQ p_base+8(FP), DI + MOVQ p_len+16(FP), DX + LEAQ -64(DI)(DX*1), DX + MOVQ DX, 512(SP) + CMPQ DX, DI + JE avx2_only_one_block + + // Load initial digest + MOVL (SI), AX + MOVL 4(SI), BX + MOVL 8(SI), CX + MOVL 12(SI), R8 + MOVL 16(SI), DX + MOVL 20(SI), R9 + MOVL 24(SI), R10 + MOVL 28(SI), R11 + +avx2_loop0: + // at each iteration works with one block (512 bit) + VMOVDQU (DI), Y0 + VMOVDQU 32(DI), Y1 + VMOVDQU 64(DI), Y2 + VMOVDQU 96(DI), Y3 + VMOVDQU flip_mask<>+0(SB), Y13 + + // Apply Byte Flip Mask: LE -> BE + VPSHUFB Y13, Y0, Y0 + VPSHUFB Y13, Y1, Y1 + VPSHUFB Y13, Y2, Y2 + VPSHUFB Y13, Y3, Y3 + + // Transpose data into high/low parts + VPERM2I128 $0x20, Y2, Y0, Y4 + VPERM2I128 $0x31, Y2, Y0, Y5 + VPERM2I128 $0x20, Y3, Y1, Y6 + VPERM2I128 $0x31, Y3, Y1, Y7 + LEAQ K256<>+0(SB), BP + +avx2_last_block_enter: + ADDQ $0x40, DI + MOVQ DI, 520(SP) + XORQ SI, SI + +avx2_loop1: + // Do 4 rounds and scheduling + VPADDD (BP)(SI*1), Y4, Y9 + VMOVDQU Y9, (SP)(SI*1) + MOVL AX, DI + RORXL $0x19, DX, R13 + RORXL $0x0b, DX, R14 + ADDL (SP)(SI*1), R11 + ORL CX, DI + VPALIGNR $0x04, Y6, Y7, Y0 + MOVL R9, R15 + RORXL $0x0d, AX, R12 + XORL R14, R13 + XORL R10, R15 + VPADDD Y4, Y0, Y0 + RORXL $0x06, DX, R14 + ANDL DX, R15 + XORL R14, R13 + RORXL $0x16, AX, R14 + ADDL R11, R8 + ANDL BX, DI + VPALIGNR $0x04, Y4, Y5, Y1 + XORL R12, R14 + RORXL $0x02, AX, R12 + XORL R10, R15 + VPSRLD $0x07, Y1, Y2 + XORL R12, R14 + MOVL AX, R12 + ANDL CX, R12 + ADDL R13, R15 + VPSLLD $0x19, Y1, Y3 + ORL R12, DI + ADDL R14, R11 + ADDL R15, R8 + VPOR Y2, Y3, Y3 + VPSRLD $0x12, Y1, Y2 + ADDL R15, R11 + ADDL DI, R11 + MOVL R11, DI + RORXL $0x19, R8, R13 + RORXL $0x0b, R8, R14 + ADDL 4(SP)(SI*1), R10 + ORL BX, DI + VPSRLD $0x03, Y1, Y8 + MOVL DX, R15 + RORXL $0x0d, R11, R12 + XORL R14, R13 + XORL R9, R15 + RORXL $0x06, R8, R14 + XORL R14, R13 + RORXL $0x16, R11, R14 + ANDL R8, R15 + ADDL R10, CX + VPSLLD $0x0e, Y1, Y1 + ANDL AX, DI + XORL R12, R14 + VPXOR Y1, Y3, Y3 + RORXL $0x02, R11, R12 + XORL R9, R15 + VPXOR Y2, Y3, Y3 + XORL R12, R14 + MOVL R11, R12 + ANDL BX, R12 + ADDL R13, R15 + VPXOR Y8, Y3, Y1 + VPSHUFD $0xfa, Y7, Y2 + ORL R12, DI + ADDL R14, R10 + VPADDD Y1, Y0, Y0 + ADDL R15, CX + ADDL R15, R10 + ADDL DI, R10 + VPSRLD $0x0a, Y2, Y8 + MOVL R10, DI + RORXL $0x19, CX, R13 + ADDL 8(SP)(SI*1), R9 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x0b, CX, R14 + ORL AX, DI + MOVL R8, R15 + XORL DX, R15 + RORXL $0x0d, R10, R12 + XORL R14, R13 + VPSRLQ $0x11, Y2, Y2 + ANDL CX, R15 + RORXL $0x06, CX, R14 + VPXOR Y3, Y2, Y2 + ADDL R9, BX + ANDL R11, DI + XORL R14, R13 + RORXL $0x16, R10, R14 + VPXOR Y2, Y8, Y8 + XORL DX, R15 + VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 + XORL R12, R14 + RORXL $0x02, R10, R12 + VPADDD Y8, Y0, Y0 + XORL R12, R14 + MOVL R10, R12 + ANDL AX, R12 + ADDL R13, R15 + VPSHUFD $0x50, Y0, Y2 + ORL R12, DI + ADDL R14, R9 + ADDL R15, BX + ADDL R15, R9 + ADDL DI, R9 + MOVL R9, DI + RORXL $0x19, BX, R13 + RORXL $0x0b, BX, R14 + ADDL 12(SP)(SI*1), DX + ORL R11, DI + VPSRLD $0x0a, Y2, Y11 + MOVL CX, R15 + RORXL $0x0d, R9, R12 + XORL R14, R13 + XORL R8, R15 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x06, BX, R14 + ANDL BX, R15 + ADDL DX, AX + ANDL R10, DI + VPSRLQ $0x11, Y2, Y2 + XORL R14, R13 + XORL R8, R15 + VPXOR Y3, Y2, Y2 + RORXL $0x16, R9, R14 + ADDL R13, R15 + VPXOR Y2, Y11, Y11 + XORL R12, R14 + ADDL R15, AX + RORXL $0x02, R9, R12 + VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 + VPADDD Y0, Y11, Y4 + XORL R12, R14 + MOVL R9, R12 + ANDL R11, R12 + ORL R12, DI + ADDL R14, DX + ADDL R15, DX + ADDL DI, DX + + // Do 4 rounds and scheduling + VPADDD 32(BP)(SI*1), Y5, Y9 + VMOVDQU Y9, 32(SP)(SI*1) + MOVL DX, DI + RORXL $0x19, AX, R13 + RORXL $0x0b, AX, R14 + ADDL 32(SP)(SI*1), R8 + ORL R10, DI + VPALIGNR $0x04, Y7, Y4, Y0 + MOVL BX, R15 + RORXL $0x0d, DX, R12 + XORL R14, R13 + XORL CX, R15 + VPADDD Y5, Y0, Y0 + RORXL $0x06, AX, R14 + ANDL AX, R15 + XORL R14, R13 + RORXL $0x16, DX, R14 + ADDL R8, R11 + ANDL R9, DI + VPALIGNR $0x04, Y5, Y6, Y1 + XORL R12, R14 + RORXL $0x02, DX, R12 + XORL CX, R15 + VPSRLD $0x07, Y1, Y2 + XORL R12, R14 + MOVL DX, R12 + ANDL R10, R12 + ADDL R13, R15 + VPSLLD $0x19, Y1, Y3 + ORL R12, DI + ADDL R14, R8 + ADDL R15, R11 + VPOR Y2, Y3, Y3 + VPSRLD $0x12, Y1, Y2 + ADDL R15, R8 + ADDL DI, R8 + MOVL R8, DI + RORXL $0x19, R11, R13 + RORXL $0x0b, R11, R14 + ADDL 36(SP)(SI*1), CX + ORL R9, DI + VPSRLD $0x03, Y1, Y8 + MOVL AX, R15 + RORXL $0x0d, R8, R12 + XORL R14, R13 + XORL BX, R15 + RORXL $0x06, R11, R14 + XORL R14, R13 + RORXL $0x16, R8, R14 + ANDL R11, R15 + ADDL CX, R10 + VPSLLD $0x0e, Y1, Y1 + ANDL DX, DI + XORL R12, R14 + VPXOR Y1, Y3, Y3 + RORXL $0x02, R8, R12 + XORL BX, R15 + VPXOR Y2, Y3, Y3 + XORL R12, R14 + MOVL R8, R12 + ANDL R9, R12 + ADDL R13, R15 + VPXOR Y8, Y3, Y1 + VPSHUFD $0xfa, Y4, Y2 + ORL R12, DI + ADDL R14, CX + VPADDD Y1, Y0, Y0 + ADDL R15, R10 + ADDL R15, CX + ADDL DI, CX + VPSRLD $0x0a, Y2, Y8 + MOVL CX, DI + RORXL $0x19, R10, R13 + ADDL 40(SP)(SI*1), BX + VPSRLQ $0x13, Y2, Y3 + RORXL $0x0b, R10, R14 + ORL DX, DI + MOVL R11, R15 + XORL AX, R15 + RORXL $0x0d, CX, R12 + XORL R14, R13 + VPSRLQ $0x11, Y2, Y2 + ANDL R10, R15 + RORXL $0x06, R10, R14 + VPXOR Y3, Y2, Y2 + ADDL BX, R9 + ANDL R8, DI + XORL R14, R13 + RORXL $0x16, CX, R14 + VPXOR Y2, Y8, Y8 + XORL AX, R15 + VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 + XORL R12, R14 + RORXL $0x02, CX, R12 + VPADDD Y8, Y0, Y0 + XORL R12, R14 + MOVL CX, R12 + ANDL DX, R12 + ADDL R13, R15 + VPSHUFD $0x50, Y0, Y2 + ORL R12, DI + ADDL R14, BX + ADDL R15, R9 + ADDL R15, BX + ADDL DI, BX + MOVL BX, DI + RORXL $0x19, R9, R13 + RORXL $0x0b, R9, R14 + ADDL 44(SP)(SI*1), AX + ORL R8, DI + VPSRLD $0x0a, Y2, Y11 + MOVL R10, R15 + RORXL $0x0d, BX, R12 + XORL R14, R13 + XORL R11, R15 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x06, R9, R14 + ANDL R9, R15 + ADDL AX, DX + ANDL CX, DI + VPSRLQ $0x11, Y2, Y2 + XORL R14, R13 + XORL R11, R15 + VPXOR Y3, Y2, Y2 + RORXL $0x16, BX, R14 + ADDL R13, R15 + VPXOR Y2, Y11, Y11 + XORL R12, R14 + ADDL R15, DX + RORXL $0x02, BX, R12 + VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 + VPADDD Y0, Y11, Y5 + XORL R12, R14 + MOVL BX, R12 + ANDL R8, R12 + ORL R12, DI + ADDL R14, AX + ADDL R15, AX + ADDL DI, AX + + // Do 4 rounds and scheduling + VPADDD 64(BP)(SI*1), Y6, Y9 + VMOVDQU Y9, 64(SP)(SI*1) + MOVL AX, DI + RORXL $0x19, DX, R13 + RORXL $0x0b, DX, R14 + ADDL 64(SP)(SI*1), R11 + ORL CX, DI + VPALIGNR $0x04, Y4, Y5, Y0 + MOVL R9, R15 + RORXL $0x0d, AX, R12 + XORL R14, R13 + XORL R10, R15 + VPADDD Y6, Y0, Y0 + RORXL $0x06, DX, R14 + ANDL DX, R15 + XORL R14, R13 + RORXL $0x16, AX, R14 + ADDL R11, R8 + ANDL BX, DI + VPALIGNR $0x04, Y6, Y7, Y1 + XORL R12, R14 + RORXL $0x02, AX, R12 + XORL R10, R15 + VPSRLD $0x07, Y1, Y2 + XORL R12, R14 + MOVL AX, R12 + ANDL CX, R12 + ADDL R13, R15 + VPSLLD $0x19, Y1, Y3 + ORL R12, DI + ADDL R14, R11 + ADDL R15, R8 + VPOR Y2, Y3, Y3 + VPSRLD $0x12, Y1, Y2 + ADDL R15, R11 + ADDL DI, R11 + MOVL R11, DI + RORXL $0x19, R8, R13 + RORXL $0x0b, R8, R14 + ADDL 68(SP)(SI*1), R10 + ORL BX, DI + VPSRLD $0x03, Y1, Y8 + MOVL DX, R15 + RORXL $0x0d, R11, R12 + XORL R14, R13 + XORL R9, R15 + RORXL $0x06, R8, R14 + XORL R14, R13 + RORXL $0x16, R11, R14 + ANDL R8, R15 + ADDL R10, CX + VPSLLD $0x0e, Y1, Y1 + ANDL AX, DI + XORL R12, R14 + VPXOR Y1, Y3, Y3 + RORXL $0x02, R11, R12 + XORL R9, R15 + VPXOR Y2, Y3, Y3 + XORL R12, R14 + MOVL R11, R12 + ANDL BX, R12 + ADDL R13, R15 + VPXOR Y8, Y3, Y1 + VPSHUFD $0xfa, Y5, Y2 + ORL R12, DI + ADDL R14, R10 + VPADDD Y1, Y0, Y0 + ADDL R15, CX + ADDL R15, R10 + ADDL DI, R10 + VPSRLD $0x0a, Y2, Y8 + MOVL R10, DI + RORXL $0x19, CX, R13 + ADDL 72(SP)(SI*1), R9 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x0b, CX, R14 + ORL AX, DI + MOVL R8, R15 + XORL DX, R15 + RORXL $0x0d, R10, R12 + XORL R14, R13 + VPSRLQ $0x11, Y2, Y2 + ANDL CX, R15 + RORXL $0x06, CX, R14 + VPXOR Y3, Y2, Y2 + ADDL R9, BX + ANDL R11, DI + XORL R14, R13 + RORXL $0x16, R10, R14 + VPXOR Y2, Y8, Y8 + XORL DX, R15 + VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 + XORL R12, R14 + RORXL $0x02, R10, R12 + VPADDD Y8, Y0, Y0 + XORL R12, R14 + MOVL R10, R12 + ANDL AX, R12 + ADDL R13, R15 + VPSHUFD $0x50, Y0, Y2 + ORL R12, DI + ADDL R14, R9 + ADDL R15, BX + ADDL R15, R9 + ADDL DI, R9 + MOVL R9, DI + RORXL $0x19, BX, R13 + RORXL $0x0b, BX, R14 + ADDL 76(SP)(SI*1), DX + ORL R11, DI + VPSRLD $0x0a, Y2, Y11 + MOVL CX, R15 + RORXL $0x0d, R9, R12 + XORL R14, R13 + XORL R8, R15 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x06, BX, R14 + ANDL BX, R15 + ADDL DX, AX + ANDL R10, DI + VPSRLQ $0x11, Y2, Y2 + XORL R14, R13 + XORL R8, R15 + VPXOR Y3, Y2, Y2 + RORXL $0x16, R9, R14 + ADDL R13, R15 + VPXOR Y2, Y11, Y11 + XORL R12, R14 + ADDL R15, AX + RORXL $0x02, R9, R12 + VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 + VPADDD Y0, Y11, Y6 + XORL R12, R14 + MOVL R9, R12 + ANDL R11, R12 + ORL R12, DI + ADDL R14, DX + ADDL R15, DX + ADDL DI, DX + + // Do 4 rounds and scheduling + VPADDD 96(BP)(SI*1), Y7, Y9 + VMOVDQU Y9, 96(SP)(SI*1) + MOVL DX, DI + RORXL $0x19, AX, R13 + RORXL $0x0b, AX, R14 + ADDL 96(SP)(SI*1), R8 + ORL R10, DI + VPALIGNR $0x04, Y5, Y6, Y0 + MOVL BX, R15 + RORXL $0x0d, DX, R12 + XORL R14, R13 + XORL CX, R15 + VPADDD Y7, Y0, Y0 + RORXL $0x06, AX, R14 + ANDL AX, R15 + XORL R14, R13 + RORXL $0x16, DX, R14 + ADDL R8, R11 + ANDL R9, DI + VPALIGNR $0x04, Y7, Y4, Y1 + XORL R12, R14 + RORXL $0x02, DX, R12 + XORL CX, R15 + VPSRLD $0x07, Y1, Y2 + XORL R12, R14 + MOVL DX, R12 + ANDL R10, R12 + ADDL R13, R15 + VPSLLD $0x19, Y1, Y3 + ORL R12, DI + ADDL R14, R8 + ADDL R15, R11 + VPOR Y2, Y3, Y3 + VPSRLD $0x12, Y1, Y2 + ADDL R15, R8 + ADDL DI, R8 + MOVL R8, DI + RORXL $0x19, R11, R13 + RORXL $0x0b, R11, R14 + ADDL 100(SP)(SI*1), CX + ORL R9, DI + VPSRLD $0x03, Y1, Y8 + MOVL AX, R15 + RORXL $0x0d, R8, R12 + XORL R14, R13 + XORL BX, R15 + RORXL $0x06, R11, R14 + XORL R14, R13 + RORXL $0x16, R8, R14 + ANDL R11, R15 + ADDL CX, R10 + VPSLLD $0x0e, Y1, Y1 + ANDL DX, DI + XORL R12, R14 + VPXOR Y1, Y3, Y3 + RORXL $0x02, R8, R12 + XORL BX, R15 + VPXOR Y2, Y3, Y3 + XORL R12, R14 + MOVL R8, R12 + ANDL R9, R12 + ADDL R13, R15 + VPXOR Y8, Y3, Y1 + VPSHUFD $0xfa, Y6, Y2 + ORL R12, DI + ADDL R14, CX + VPADDD Y1, Y0, Y0 + ADDL R15, R10 + ADDL R15, CX + ADDL DI, CX + VPSRLD $0x0a, Y2, Y8 + MOVL CX, DI + RORXL $0x19, R10, R13 + ADDL 104(SP)(SI*1), BX + VPSRLQ $0x13, Y2, Y3 + RORXL $0x0b, R10, R14 + ORL DX, DI + MOVL R11, R15 + XORL AX, R15 + RORXL $0x0d, CX, R12 + XORL R14, R13 + VPSRLQ $0x11, Y2, Y2 + ANDL R10, R15 + RORXL $0x06, R10, R14 + VPXOR Y3, Y2, Y2 + ADDL BX, R9 + ANDL R8, DI + XORL R14, R13 + RORXL $0x16, CX, R14 + VPXOR Y2, Y8, Y8 + XORL AX, R15 + VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 + XORL R12, R14 + RORXL $0x02, CX, R12 + VPADDD Y8, Y0, Y0 + XORL R12, R14 + MOVL CX, R12 + ANDL DX, R12 + ADDL R13, R15 + VPSHUFD $0x50, Y0, Y2 + ORL R12, DI + ADDL R14, BX + ADDL R15, R9 + ADDL R15, BX + ADDL DI, BX + MOVL BX, DI + RORXL $0x19, R9, R13 + RORXL $0x0b, R9, R14 + ADDL 108(SP)(SI*1), AX + ORL R8, DI + VPSRLD $0x0a, Y2, Y11 + MOVL R10, R15 + RORXL $0x0d, BX, R12 + XORL R14, R13 + XORL R11, R15 + VPSRLQ $0x13, Y2, Y3 + RORXL $0x06, R9, R14 + ANDL R9, R15 + ADDL AX, DX + ANDL CX, DI + VPSRLQ $0x11, Y2, Y2 + XORL R14, R13 + XORL R11, R15 + VPXOR Y3, Y2, Y2 + RORXL $0x16, BX, R14 + ADDL R13, R15 + VPXOR Y2, Y11, Y11 + XORL R12, R14 + ADDL R15, DX + RORXL $0x02, BX, R12 + VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 + VPADDD Y0, Y11, Y7 + XORL R12, R14 + MOVL BX, R12 + ANDL R8, R12 + ORL R12, DI + ADDL R14, AX + ADDL R15, AX + ADDL DI, AX + ADDQ $0x80, SI + CMPQ SI, $0x00000180 + JB avx2_loop1 + +avx2_loop2: + VPADDD (BP)(SI*1), Y4, Y9 + VMOVDQU Y9, (SP)(SI*1) + MOVL R9, R15 + RORXL $0x19, DX, R13 + RORXL $0x0b, DX, R14 + XORL R10, R15 + XORL R14, R13 + RORXL $0x06, DX, R14 + ANDL DX, R15 + XORL R14, R13 + RORXL $0x0d, AX, R12 + XORL R10, R15 + RORXL $0x16, AX, R14 + MOVL AX, DI + XORL R12, R14 + RORXL $0x02, AX, R12 + ADDL (SP)(SI*1), R11 + ORL CX, DI + XORL R12, R14 + MOVL AX, R12 + ANDL BX, DI + ANDL CX, R12 + ADDL R13, R15 + ADDL R11, R8 + ORL R12, DI + ADDL R14, R11 + ADDL R15, R8 + ADDL R15, R11 + MOVL DX, R15 + RORXL $0x19, R8, R13 + RORXL $0x0b, R8, R14 + XORL R9, R15 + XORL R14, R13 + RORXL $0x06, R8, R14 + ANDL R8, R15 + ADDL DI, R11 + XORL R14, R13 + RORXL $0x0d, R11, R12 + XORL R9, R15 + RORXL $0x16, R11, R14 + MOVL R11, DI + XORL R12, R14 + RORXL $0x02, R11, R12 + ADDL 4(SP)(SI*1), R10 + ORL BX, DI + XORL R12, R14 + MOVL R11, R12 + ANDL AX, DI + ANDL BX, R12 + ADDL R13, R15 + ADDL R10, CX + ORL R12, DI + ADDL R14, R10 + ADDL R15, CX + ADDL R15, R10 + MOVL R8, R15 + RORXL $0x19, CX, R13 + RORXL $0x0b, CX, R14 + XORL DX, R15 + XORL R14, R13 + RORXL $0x06, CX, R14 + ANDL CX, R15 + ADDL DI, R10 + XORL R14, R13 + RORXL $0x0d, R10, R12 + XORL DX, R15 + RORXL $0x16, R10, R14 + MOVL R10, DI + XORL R12, R14 + RORXL $0x02, R10, R12 + ADDL 8(SP)(SI*1), R9 + ORL AX, DI + XORL R12, R14 + MOVL R10, R12 + ANDL R11, DI + ANDL AX, R12 + ADDL R13, R15 + ADDL R9, BX + ORL R12, DI + ADDL R14, R9 + ADDL R15, BX + ADDL R15, R9 + MOVL CX, R15 + RORXL $0x19, BX, R13 + RORXL $0x0b, BX, R14 + XORL R8, R15 + XORL R14, R13 + RORXL $0x06, BX, R14 + ANDL BX, R15 + ADDL DI, R9 + XORL R14, R13 + RORXL $0x0d, R9, R12 + XORL R8, R15 + RORXL $0x16, R9, R14 + MOVL R9, DI + XORL R12, R14 + RORXL $0x02, R9, R12 + ADDL 12(SP)(SI*1), DX + ORL R11, DI + XORL R12, R14 + MOVL R9, R12 + ANDL R10, DI + ANDL R11, R12 + ADDL R13, R15 + ADDL DX, AX + ORL R12, DI + ADDL R14, DX + ADDL R15, AX + ADDL R15, DX + ADDL DI, DX + VPADDD 32(BP)(SI*1), Y5, Y9 + VMOVDQU Y9, 32(SP)(SI*1) + MOVL BX, R15 + RORXL $0x19, AX, R13 + RORXL $0x0b, AX, R14 + XORL CX, R15 + XORL R14, R13 + RORXL $0x06, AX, R14 + ANDL AX, R15 + XORL R14, R13 + RORXL $0x0d, DX, R12 + XORL CX, R15 + RORXL $0x16, DX, R14 + MOVL DX, DI + XORL R12, R14 + RORXL $0x02, DX, R12 + ADDL 32(SP)(SI*1), R8 + ORL R10, DI + XORL R12, R14 + MOVL DX, R12 + ANDL R9, DI + ANDL R10, R12 + ADDL R13, R15 + ADDL R8, R11 + ORL R12, DI + ADDL R14, R8 + ADDL R15, R11 + ADDL R15, R8 + MOVL AX, R15 + RORXL $0x19, R11, R13 + RORXL $0x0b, R11, R14 + XORL BX, R15 + XORL R14, R13 + RORXL $0x06, R11, R14 + ANDL R11, R15 + ADDL DI, R8 + XORL R14, R13 + RORXL $0x0d, R8, R12 + XORL BX, R15 + RORXL $0x16, R8, R14 + MOVL R8, DI + XORL R12, R14 + RORXL $0x02, R8, R12 + ADDL 36(SP)(SI*1), CX + ORL R9, DI + XORL R12, R14 + MOVL R8, R12 + ANDL DX, DI + ANDL R9, R12 + ADDL R13, R15 + ADDL CX, R10 + ORL R12, DI + ADDL R14, CX + ADDL R15, R10 + ADDL R15, CX + MOVL R11, R15 + RORXL $0x19, R10, R13 + RORXL $0x0b, R10, R14 + XORL AX, R15 + XORL R14, R13 + RORXL $0x06, R10, R14 + ANDL R10, R15 + ADDL DI, CX + XORL R14, R13 + RORXL $0x0d, CX, R12 + XORL AX, R15 + RORXL $0x16, CX, R14 + MOVL CX, DI + XORL R12, R14 + RORXL $0x02, CX, R12 + ADDL 40(SP)(SI*1), BX + ORL DX, DI + XORL R12, R14 + MOVL CX, R12 + ANDL R8, DI + ANDL DX, R12 + ADDL R13, R15 + ADDL BX, R9 + ORL R12, DI + ADDL R14, BX + ADDL R15, R9 + ADDL R15, BX + MOVL R10, R15 + RORXL $0x19, R9, R13 + RORXL $0x0b, R9, R14 + XORL R11, R15 + XORL R14, R13 + RORXL $0x06, R9, R14 + ANDL R9, R15 + ADDL DI, BX + XORL R14, R13 + RORXL $0x0d, BX, R12 + XORL R11, R15 + RORXL $0x16, BX, R14 + MOVL BX, DI + XORL R12, R14 + RORXL $0x02, BX, R12 + ADDL 44(SP)(SI*1), AX + ORL R8, DI + XORL R12, R14 + MOVL BX, R12 + ANDL CX, DI + ANDL R8, R12 + ADDL R13, R15 + ADDL AX, DX + ORL R12, DI + ADDL R14, AX + ADDL R15, DX + ADDL R15, AX + ADDL DI, AX + ADDQ $0x40, SI + VMOVDQU Y6, Y4 + VMOVDQU Y7, Y5 + CMPQ SI, $0x00000200 + JB avx2_loop2 + MOVQ dig+0(FP), SI + MOVQ 520(SP), DI + ADDL AX, (SI) + MOVL (SI), AX + ADDL BX, 4(SI) + MOVL 4(SI), BX + ADDL CX, 8(SI) + MOVL 8(SI), CX + ADDL R8, 12(SI) + MOVL 12(SI), R8 + ADDL DX, 16(SI) + MOVL 16(SI), DX + ADDL R9, 20(SI) + MOVL 20(SI), R9 + ADDL R10, 24(SI) + MOVL 24(SI), R10 + ADDL R11, 28(SI) + MOVL 28(SI), R11 + CMPQ 512(SP), DI + JB done_hash + XORQ SI, SI + +avx2_loop3: + MOVL R9, R15 + RORXL $0x19, DX, R13 + RORXL $0x0b, DX, R14 + XORL R10, R15 + XORL R14, R13 + RORXL $0x06, DX, R14 + ANDL DX, R15 + XORL R14, R13 + RORXL $0x0d, AX, R12 + XORL R10, R15 + RORXL $0x16, AX, R14 + MOVL AX, DI + XORL R12, R14 + RORXL $0x02, AX, R12 + ADDL 16(SP)(SI*1), R11 + ORL CX, DI + XORL R12, R14 + MOVL AX, R12 + ANDL BX, DI + ANDL CX, R12 + ADDL R13, R15 + ADDL R11, R8 + ORL R12, DI + ADDL R14, R11 + ADDL R15, R8 + ADDL R15, R11 + MOVL DX, R15 + RORXL $0x19, R8, R13 + RORXL $0x0b, R8, R14 + XORL R9, R15 + XORL R14, R13 + RORXL $0x06, R8, R14 + ANDL R8, R15 + ADDL DI, R11 + XORL R14, R13 + RORXL $0x0d, R11, R12 + XORL R9, R15 + RORXL $0x16, R11, R14 + MOVL R11, DI + XORL R12, R14 + RORXL $0x02, R11, R12 + ADDL 20(SP)(SI*1), R10 + ORL BX, DI + XORL R12, R14 + MOVL R11, R12 + ANDL AX, DI + ANDL BX, R12 + ADDL R13, R15 + ADDL R10, CX + ORL R12, DI + ADDL R14, R10 + ADDL R15, CX + ADDL R15, R10 + MOVL R8, R15 + RORXL $0x19, CX, R13 + RORXL $0x0b, CX, R14 + XORL DX, R15 + XORL R14, R13 + RORXL $0x06, CX, R14 + ANDL CX, R15 + ADDL DI, R10 + XORL R14, R13 + RORXL $0x0d, R10, R12 + XORL DX, R15 + RORXL $0x16, R10, R14 + MOVL R10, DI + XORL R12, R14 + RORXL $0x02, R10, R12 + ADDL 24(SP)(SI*1), R9 + ORL AX, DI + XORL R12, R14 + MOVL R10, R12 + ANDL R11, DI + ANDL AX, R12 + ADDL R13, R15 + ADDL R9, BX + ORL R12, DI + ADDL R14, R9 + ADDL R15, BX + ADDL R15, R9 + MOVL CX, R15 + RORXL $0x19, BX, R13 + RORXL $0x0b, BX, R14 + XORL R8, R15 + XORL R14, R13 + RORXL $0x06, BX, R14 + ANDL BX, R15 + ADDL DI, R9 + XORL R14, R13 + RORXL $0x0d, R9, R12 + XORL R8, R15 + RORXL $0x16, R9, R14 + MOVL R9, DI + XORL R12, R14 + RORXL $0x02, R9, R12 + ADDL 28(SP)(SI*1), DX + ORL R11, DI + XORL R12, R14 + MOVL R9, R12 + ANDL R10, DI + ANDL R11, R12 + ADDL R13, R15 + ADDL DX, AX + ORL R12, DI + ADDL R14, DX + ADDL R15, AX + ADDL R15, DX + ADDL DI, DX + MOVL BX, R15 + RORXL $0x19, AX, R13 + RORXL $0x0b, AX, R14 + XORL CX, R15 + XORL R14, R13 + RORXL $0x06, AX, R14 + ANDL AX, R15 + XORL R14, R13 + RORXL $0x0d, DX, R12 + XORL CX, R15 + RORXL $0x16, DX, R14 + MOVL DX, DI + XORL R12, R14 + RORXL $0x02, DX, R12 + ADDL 48(SP)(SI*1), R8 + ORL R10, DI + XORL R12, R14 + MOVL DX, R12 + ANDL R9, DI + ANDL R10, R12 + ADDL R13, R15 + ADDL R8, R11 + ORL R12, DI + ADDL R14, R8 + ADDL R15, R11 + ADDL R15, R8 + MOVL AX, R15 + RORXL $0x19, R11, R13 + RORXL $0x0b, R11, R14 + XORL BX, R15 + XORL R14, R13 + RORXL $0x06, R11, R14 + ANDL R11, R15 + ADDL DI, R8 + XORL R14, R13 + RORXL $0x0d, R8, R12 + XORL BX, R15 + RORXL $0x16, R8, R14 + MOVL R8, DI + XORL R12, R14 + RORXL $0x02, R8, R12 + ADDL 52(SP)(SI*1), CX + ORL R9, DI + XORL R12, R14 + MOVL R8, R12 + ANDL DX, DI + ANDL R9, R12 + ADDL R13, R15 + ADDL CX, R10 + ORL R12, DI + ADDL R14, CX + ADDL R15, R10 + ADDL R15, CX + MOVL R11, R15 + RORXL $0x19, R10, R13 + RORXL $0x0b, R10, R14 + XORL AX, R15 + XORL R14, R13 + RORXL $0x06, R10, R14 + ANDL R10, R15 + ADDL DI, CX + XORL R14, R13 + RORXL $0x0d, CX, R12 + XORL AX, R15 + RORXL $0x16, CX, R14 + MOVL CX, DI + XORL R12, R14 + RORXL $0x02, CX, R12 + ADDL 56(SP)(SI*1), BX + ORL DX, DI + XORL R12, R14 + MOVL CX, R12 + ANDL R8, DI + ANDL DX, R12 + ADDL R13, R15 + ADDL BX, R9 + ORL R12, DI + ADDL R14, BX + ADDL R15, R9 + ADDL R15, BX + MOVL R10, R15 + RORXL $0x19, R9, R13 + RORXL $0x0b, R9, R14 + XORL R11, R15 + XORL R14, R13 + RORXL $0x06, R9, R14 + ANDL R9, R15 + ADDL DI, BX + XORL R14, R13 + RORXL $0x0d, BX, R12 + XORL R11, R15 + RORXL $0x16, BX, R14 + MOVL BX, DI + XORL R12, R14 + RORXL $0x02, BX, R12 + ADDL 60(SP)(SI*1), AX + ORL R8, DI + XORL R12, R14 + MOVL BX, R12 + ANDL CX, DI + ANDL R8, R12 + ADDL R13, R15 + ADDL AX, DX + ORL R12, DI + ADDL R14, AX + ADDL R15, DX + ADDL R15, AX + ADDL DI, AX + ADDQ $0x40, SI + CMPQ SI, $0x00000200 + JB avx2_loop3 + MOVQ dig+0(FP), SI + MOVQ 520(SP), DI + ADDQ $0x40, DI + ADDL AX, (SI) + MOVL (SI), AX + ADDL BX, 4(SI) + MOVL 4(SI), BX + ADDL CX, 8(SI) + MOVL 8(SI), CX + ADDL R8, 12(SI) + MOVL 12(SI), R8 + ADDL DX, 16(SI) + MOVL 16(SI), DX + ADDL R9, 20(SI) + MOVL 20(SI), R9 + ADDL R10, 24(SI) + MOVL 24(SI), R10 + ADDL R11, 28(SI) + MOVL 28(SI), R11 + CMPQ 512(SP), DI + JA avx2_loop0 + JB done_hash + +avx2_do_last_block: + VMOVDQU (DI), X4 + VMOVDQU 16(DI), X5 + VMOVDQU 32(DI), X6 + VMOVDQU 48(DI), X7 + VMOVDQU flip_mask<>+0(SB), Y13 + VPSHUFB X13, X4, X4 + VPSHUFB X13, X5, X5 + VPSHUFB X13, X6, X6 + VPSHUFB X13, X7, X7 + LEAQ K256<>+0(SB), BP + JMP avx2_last_block_enter + +avx2_only_one_block: + MOVL (SI), AX + MOVL 4(SI), BX + MOVL 8(SI), CX + MOVL 12(SI), R8 + MOVL 16(SI), DX + MOVL 20(SI), R9 + MOVL 24(SI), R10 + MOVL 28(SI), R11 + JMP avx2_do_last_block + +done_hash: + VZEROUPPER + RET + +DATA flip_mask<>+0(SB)/8, $0x0405060700010203 +DATA flip_mask<>+8(SB)/8, $0x0c0d0e0f08090a0b +DATA flip_mask<>+16(SB)/8, $0x0405060700010203 +DATA flip_mask<>+24(SB)/8, $0x0c0d0e0f08090a0b +GLOBL flip_mask<>(SB), RODATA, $32 + +DATA K256<>+0(SB)/4, $0x428a2f98 +DATA K256<>+4(SB)/4, $0x71374491 +DATA K256<>+8(SB)/4, $0xb5c0fbcf +DATA K256<>+12(SB)/4, $0xe9b5dba5 +DATA K256<>+16(SB)/4, $0x428a2f98 +DATA K256<>+20(SB)/4, $0x71374491 +DATA K256<>+24(SB)/4, $0xb5c0fbcf +DATA K256<>+28(SB)/4, $0xe9b5dba5 +DATA K256<>+32(SB)/4, $0x3956c25b +DATA K256<>+36(SB)/4, $0x59f111f1 +DATA K256<>+40(SB)/4, $0x923f82a4 +DATA K256<>+44(SB)/4, $0xab1c5ed5 +DATA K256<>+48(SB)/4, $0x3956c25b +DATA K256<>+52(SB)/4, $0x59f111f1 +DATA K256<>+56(SB)/4, $0x923f82a4 +DATA K256<>+60(SB)/4, $0xab1c5ed5 +DATA K256<>+64(SB)/4, $0xd807aa98 +DATA K256<>+68(SB)/4, $0x12835b01 +DATA K256<>+72(SB)/4, $0x243185be +DATA K256<>+76(SB)/4, $0x550c7dc3 +DATA K256<>+80(SB)/4, $0xd807aa98 +DATA K256<>+84(SB)/4, $0x12835b01 +DATA K256<>+88(SB)/4, $0x243185be +DATA K256<>+92(SB)/4, $0x550c7dc3 +DATA K256<>+96(SB)/4, $0x72be5d74 +DATA K256<>+100(SB)/4, $0x80deb1fe +DATA K256<>+104(SB)/4, $0x9bdc06a7 +DATA K256<>+108(SB)/4, $0xc19bf174 +DATA K256<>+112(SB)/4, $0x72be5d74 +DATA K256<>+116(SB)/4, $0x80deb1fe +DATA K256<>+120(SB)/4, $0x9bdc06a7 +DATA K256<>+124(SB)/4, $0xc19bf174 +DATA K256<>+128(SB)/4, $0xe49b69c1 +DATA K256<>+132(SB)/4, $0xefbe4786 +DATA K256<>+136(SB)/4, $0x0fc19dc6 +DATA K256<>+140(SB)/4, $0x240ca1cc +DATA K256<>+144(SB)/4, $0xe49b69c1 +DATA K256<>+148(SB)/4, $0xefbe4786 +DATA K256<>+152(SB)/4, $0x0fc19dc6 +DATA K256<>+156(SB)/4, $0x240ca1cc +DATA K256<>+160(SB)/4, $0x2de92c6f +DATA K256<>+164(SB)/4, $0x4a7484aa +DATA K256<>+168(SB)/4, $0x5cb0a9dc +DATA K256<>+172(SB)/4, $0x76f988da +DATA K256<>+176(SB)/4, $0x2de92c6f +DATA K256<>+180(SB)/4, $0x4a7484aa +DATA K256<>+184(SB)/4, $0x5cb0a9dc +DATA K256<>+188(SB)/4, $0x76f988da +DATA K256<>+192(SB)/4, $0x983e5152 +DATA K256<>+196(SB)/4, $0xa831c66d +DATA K256<>+200(SB)/4, $0xb00327c8 +DATA K256<>+204(SB)/4, $0xbf597fc7 +DATA K256<>+208(SB)/4, $0x983e5152 +DATA K256<>+212(SB)/4, $0xa831c66d +DATA K256<>+216(SB)/4, $0xb00327c8 +DATA K256<>+220(SB)/4, $0xbf597fc7 +DATA K256<>+224(SB)/4, $0xc6e00bf3 +DATA K256<>+228(SB)/4, $0xd5a79147 +DATA K256<>+232(SB)/4, $0x06ca6351 +DATA K256<>+236(SB)/4, $0x14292967 +DATA K256<>+240(SB)/4, $0xc6e00bf3 +DATA K256<>+244(SB)/4, $0xd5a79147 +DATA K256<>+248(SB)/4, $0x06ca6351 +DATA K256<>+252(SB)/4, $0x14292967 +DATA K256<>+256(SB)/4, $0x27b70a85 +DATA K256<>+260(SB)/4, $0x2e1b2138 +DATA K256<>+264(SB)/4, $0x4d2c6dfc +DATA K256<>+268(SB)/4, $0x53380d13 +DATA K256<>+272(SB)/4, $0x27b70a85 +DATA K256<>+276(SB)/4, $0x2e1b2138 +DATA K256<>+280(SB)/4, $0x4d2c6dfc +DATA K256<>+284(SB)/4, $0x53380d13 +DATA K256<>+288(SB)/4, $0x650a7354 +DATA K256<>+292(SB)/4, $0x766a0abb +DATA K256<>+296(SB)/4, $0x81c2c92e +DATA K256<>+300(SB)/4, $0x92722c85 +DATA K256<>+304(SB)/4, $0x650a7354 +DATA K256<>+308(SB)/4, $0x766a0abb +DATA K256<>+312(SB)/4, $0x81c2c92e +DATA K256<>+316(SB)/4, $0x92722c85 +DATA K256<>+320(SB)/4, $0xa2bfe8a1 +DATA K256<>+324(SB)/4, $0xa81a664b +DATA K256<>+328(SB)/4, $0xc24b8b70 +DATA K256<>+332(SB)/4, $0xc76c51a3 +DATA K256<>+336(SB)/4, $0xa2bfe8a1 +DATA K256<>+340(SB)/4, $0xa81a664b +DATA K256<>+344(SB)/4, $0xc24b8b70 +DATA K256<>+348(SB)/4, $0xc76c51a3 +DATA K256<>+352(SB)/4, $0xd192e819 +DATA K256<>+356(SB)/4, $0xd6990624 +DATA K256<>+360(SB)/4, $0xf40e3585 +DATA K256<>+364(SB)/4, $0x106aa070 +DATA K256<>+368(SB)/4, $0xd192e819 +DATA K256<>+372(SB)/4, $0xd6990624 +DATA K256<>+376(SB)/4, $0xf40e3585 +DATA K256<>+380(SB)/4, $0x106aa070 +DATA K256<>+384(SB)/4, $0x19a4c116 +DATA K256<>+388(SB)/4, $0x1e376c08 +DATA K256<>+392(SB)/4, $0x2748774c +DATA K256<>+396(SB)/4, $0x34b0bcb5 +DATA K256<>+400(SB)/4, $0x19a4c116 +DATA K256<>+404(SB)/4, $0x1e376c08 +DATA K256<>+408(SB)/4, $0x2748774c +DATA K256<>+412(SB)/4, $0x34b0bcb5 +DATA K256<>+416(SB)/4, $0x391c0cb3 +DATA K256<>+420(SB)/4, $0x4ed8aa4a +DATA K256<>+424(SB)/4, $0x5b9cca4f +DATA K256<>+428(SB)/4, $0x682e6ff3 +DATA K256<>+432(SB)/4, $0x391c0cb3 +DATA K256<>+436(SB)/4, $0x4ed8aa4a +DATA K256<>+440(SB)/4, $0x5b9cca4f +DATA K256<>+444(SB)/4, $0x682e6ff3 +DATA K256<>+448(SB)/4, $0x748f82ee +DATA K256<>+452(SB)/4, $0x78a5636f +DATA K256<>+456(SB)/4, $0x84c87814 +DATA K256<>+460(SB)/4, $0x8cc70208 +DATA K256<>+464(SB)/4, $0x748f82ee +DATA K256<>+468(SB)/4, $0x78a5636f +DATA K256<>+472(SB)/4, $0x84c87814 +DATA K256<>+476(SB)/4, $0x8cc70208 +DATA K256<>+480(SB)/4, $0x90befffa +DATA K256<>+484(SB)/4, $0xa4506ceb +DATA K256<>+488(SB)/4, $0xbef9a3f7 +DATA K256<>+492(SB)/4, $0xc67178f2 +DATA K256<>+496(SB)/4, $0x90befffa +DATA K256<>+500(SB)/4, $0xa4506ceb +DATA K256<>+504(SB)/4, $0xbef9a3f7 +DATA K256<>+508(SB)/4, $0xc67178f2 +GLOBL K256<>(SB), RODATA|NOPTR, $512 + +DATA shuff_00BA<>+0(SB)/8, $0x0b0a090803020100 +DATA shuff_00BA<>+8(SB)/8, $0xffffffffffffffff +DATA shuff_00BA<>+16(SB)/8, $0x0b0a090803020100 +DATA shuff_00BA<>+24(SB)/8, $0xffffffffffffffff +GLOBL shuff_00BA<>(SB), RODATA, $32 + +DATA shuff_DC00<>+0(SB)/8, $0xffffffffffffffff +DATA shuff_DC00<>+8(SB)/8, $0x0b0a090803020100 +DATA shuff_DC00<>+16(SB)/8, $0xffffffffffffffff +DATA shuff_DC00<>+24(SB)/8, $0x0b0a090803020100 +GLOBL shuff_DC00<>(SB), RODATA, $32 + +// func blockSHANI(dig *Digest, p []byte) +// Requires: AVX, SHA, SSE2, SSE4.1, SSSE3 +TEXT ·blockSHANI(SB), $0-32 + MOVQ dig+0(FP), DI + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $0x06, DX + SHLQ $0x06, DX + CMPQ DX, $0x00 + JEQ done + ADDQ SI, DX + VMOVDQU (DI), X1 + VMOVDQU 16(DI), X2 + PSHUFD $0xb1, X1, X1 + PSHUFD $0x1b, X2, X2 + VMOVDQA X1, X7 + PALIGNR $0x08, X2, X1 + PBLENDW $0xf0, X7, X2 + VMOVDQA flip_mask<>+0(SB), X8 + LEAQ K256<>+0(SB), AX + +roundLoop: + // save hash values for addition after rounds + VMOVDQA X1, X9 + VMOVDQA X2, X10 + + // do rounds 0-59 + VMOVDQU (SI), X0 + PSHUFB X8, X0 + VMOVDQA X0, X3 + PADDD (AX), X0 + SHA256RNDS2 X0, X1, X2 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + VMOVDQU 16(SI), X0 + PSHUFB X8, X0 + VMOVDQA X0, X4 + PADDD 32(AX), X0 + SHA256RNDS2 X0, X1, X2 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X4, X3 + VMOVDQU 32(SI), X0 + PSHUFB X8, X0 + VMOVDQA X0, X5 + PADDD 64(AX), X0 + SHA256RNDS2 X0, X1, X2 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X5, X4 + VMOVDQU 48(SI), X0 + PSHUFB X8, X0 + VMOVDQA X0, X6 + PADDD 96(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X6, X7 + PALIGNR $0x04, X5, X7 + PADDD X7, X3 + SHA256MSG2 X6, X3 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X6, X5 + VMOVDQA X3, X0 + PADDD 128(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X3, X7 + PALIGNR $0x04, X6, X7 + PADDD X7, X4 + SHA256MSG2 X3, X4 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X3, X6 + VMOVDQA X4, X0 + PADDD 160(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X4, X7 + PALIGNR $0x04, X3, X7 + PADDD X7, X5 + SHA256MSG2 X4, X5 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X4, X3 + VMOVDQA X5, X0 + PADDD 192(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X5, X7 + PALIGNR $0x04, X4, X7 + PADDD X7, X6 + SHA256MSG2 X5, X6 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X5, X4 + VMOVDQA X6, X0 + PADDD 224(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X6, X7 + PALIGNR $0x04, X5, X7 + PADDD X7, X3 + SHA256MSG2 X6, X3 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X6, X5 + VMOVDQA X3, X0 + PADDD 256(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X3, X7 + PALIGNR $0x04, X6, X7 + PADDD X7, X4 + SHA256MSG2 X3, X4 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X3, X6 + VMOVDQA X4, X0 + PADDD 288(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X4, X7 + PALIGNR $0x04, X3, X7 + PADDD X7, X5 + SHA256MSG2 X4, X5 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X4, X3 + VMOVDQA X5, X0 + PADDD 320(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X5, X7 + PALIGNR $0x04, X4, X7 + PADDD X7, X6 + SHA256MSG2 X5, X6 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X5, X4 + VMOVDQA X6, X0 + PADDD 352(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X6, X7 + PALIGNR $0x04, X5, X7 + PADDD X7, X3 + SHA256MSG2 X6, X3 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X6, X5 + VMOVDQA X3, X0 + PADDD 384(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X3, X7 + PALIGNR $0x04, X6, X7 + PADDD X7, X4 + SHA256MSG2 X3, X4 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + SHA256MSG1 X3, X6 + VMOVDQA X4, X0 + PADDD 416(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X4, X7 + PALIGNR $0x04, X3, X7 + PADDD X7, X5 + SHA256MSG2 X4, X5 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + VMOVDQA X5, X0 + PADDD 448(AX), X0 + SHA256RNDS2 X0, X1, X2 + VMOVDQA X5, X7 + PALIGNR $0x04, X4, X7 + PADDD X7, X6 + SHA256MSG2 X5, X6 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + + // do rounds 60-63 + VMOVDQA X6, X0 + PADDD 480(AX), X0 + SHA256RNDS2 X0, X1, X2 + PSHUFD $0x0e, X0, X0 + SHA256RNDS2 X0, X2, X1 + + // add current hash values with previously saved + PADDD X9, X1 + PADDD X10, X2 + + // advance data pointer; loop until buffer empty + ADDQ $0x40, SI + CMPQ DX, SI + JNE roundLoop + + // write hash values back in the correct order + PSHUFD $0x1b, X1, X1 + PSHUFD $0xb1, X2, X2 + VMOVDQA X1, X7 + PBLENDW $0xf0, X2, X1 + PALIGNR $0x08, X7, X2 + VMOVDQU X1, (DI) + VMOVDQU X2, 16(DI) + +done: + RET diff --git a/crypto/internal/fips140/sha256/sha256block_arm64.go b/crypto/internal/fips140/sha256/sha256block_arm64.go new file mode 100644 index 00000000000..a4c341a87d6 --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256block_arm64.go @@ -0,0 +1,29 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha256 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useSHA2 = cpu.ARM64HasSHA2 + +func init() { + impl.Register("sha256", "Armv8.0", &useSHA2) +} + +//go:noescape +func blockSHA2(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useSHA2 { + blockSHA2(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha256/sha256block_arm64.s b/crypto/internal/fips140/sha256/sha256block_arm64.s similarity index 93% rename from crypto/sha256/sha256block_arm64.s rename to crypto/internal/fips140/sha256/sha256block_arm64.s index 6757310c34e..b4082607990 100644 --- a/crypto/sha256/sha256block_arm64.s +++ b/crypto/internal/fips140/sha256/sha256block_arm64.s @@ -11,12 +11,12 @@ SHA256H2 V9.S4, V8, V3 \ VMOV V2.B16, V8.B16 -// func sha256block(h []uint32, p []byte, k []uint32) -TEXT ·sha256block(SB),NOSPLIT,$0 - MOVD h_base+0(FP), R0 // Hash value first address - MOVD p_base+24(FP), R1 // message first address - MOVD k_base+48(FP), R2 // k constants first address - MOVD p_len+32(FP), R3 // message length +// func blockSHA2(dig *Digest, p []byte) +TEXT ·blockSHA2(SB),NOSPLIT,$0 + MOVD dig+0(FP), R0 // Hash value first address + MOVD p_base+8(FP), R1 // message first address + MOVD p_len+16(FP), R3 // message length + MOVD $·_K+0(SB), R2 // k constants first address VLD1 (R0), [V0.S4, V1.S4] // load h(a,b,c,d,e,f,g,h) VLD1.P 64(R2), [V16.S4, V17.S4, V18.S4, V19.S4] VLD1.P 64(R2), [V20.S4, V21.S4, V22.S4, V23.S4] diff --git a/crypto/sha256/sha256block_decl.go b/crypto/internal/fips140/sha256/sha256block_asm.go similarity index 61% rename from crypto/sha256/sha256block_decl.go rename to crypto/internal/fips140/sha256/sha256block_asm.go index e7930393874..1b157d744d6 100644 --- a/crypto/sha256/sha256block_decl.go +++ b/crypto/internal/fips140/sha256/sha256block_asm.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (386 || amd64 || loong64 || ppc64 || ppc64le || riscv64 || s390x) && !purego +//go:build (386 || loong64 || riscv64) && !purego package sha256 //go:noescape -func block(dig *digest, p []byte) +func block(dig *Digest, p []byte) diff --git a/crypto/sha256/sha256block_loong64.s b/crypto/internal/fips140/sha256/sha256block_loong64.s similarity index 95% rename from crypto/sha256/sha256block_loong64.s rename to crypto/internal/fips140/sha256/sha256block_loong64.s index 2a2fbe68337..e171d93e0ba 100644 --- a/crypto/sha256/sha256block_loong64.s +++ b/crypto/internal/fips140/sha256/sha256block_loong64.s @@ -56,7 +56,7 @@ // W[i] = M[i]; for 0 <= i <= 15 #define LOAD0(index) \ MOVW (index*4)(R5), REGTMP4; \ - WORD $0x38e7; \ // REVB2W REGTMP4, REGTMP4 to big-endian + REVB2W REGTMP4, REGTMP4; \ MOVW REGTMP4, (index*4)(R3) // W[i] = SIGMA1(W[i-2]) + W[i-7] + SIGMA0(W[i-15]) + W[i-16]; for 16 <= i <= 63 @@ -87,38 +87,37 @@ // T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + K[i] + W[i] // BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) // Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +// = ((y XOR z) AND x) XOR z // Calculate T1 in REGTMP4 #define SHA256T1(const, e, f, g, h) \ ADDV $const, h; \ ADD REGTMP4, h; \ - ROTR $6, e, REGTMP4; \ + ROTR $6, e, REGTMP5; \ ROTR $11, e, REGTMP; \ ROTR $25, e, REGTMP3; \ - AND f, e, REGTMP2; \ - XOR REGTMP, REGTMP4; \ - MOVV $0xffffffff, REGTMP; \ - XOR REGTMP4, REGTMP3; \ - XOR REGTMP, e, REGTMP5; \ + XOR f, g, REGTMP2; \ + XOR REGTMP, REGTMP5; \ + AND e, REGTMP2; \ + XOR REGTMP5, REGTMP3; \ + XOR g, REGTMP2; \ ADD REGTMP3, h; \ - AND g, REGTMP5; \ - XOR REGTMP2, REGTMP5; \ - ADD h, REGTMP5, REGTMP4 + ADD h, REGTMP2, REGTMP4 // T2 = BIGSIGMA0(a) + Maj(a, b, c) // BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) // Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +// = ((y XOR z) AND x) XOR (y AND z) // Calculate T2 in REGTMP1 #define SHA256T2(a, b, c) \ ROTR $2, a, REGTMP5; \ - AND b, c, REGTMP1; \ ROTR $13, a, REGTMP3; \ - AND c, a, REGTMP; \ - XOR REGTMP3, REGTMP5; \ - XOR REGTMP, REGTMP1; \ ROTR $22, a, REGTMP2; \ - AND a, b, REGTMP3; \ + XOR b, c, REGTMP; \ + AND b, c, REGTMP1; \ + XOR REGTMP3, REGTMP5; \ + AND REGTMP, a, REGTMP; \ XOR REGTMP2, REGTMP5; \ - XOR REGTMP3, REGTMP1; \ + XOR REGTMP, REGTMP1; \ ADD REGTMP5, REGTMP1 // Calculate T1 and T2, then e = d + T1 and a = T1 + T2. @@ -141,7 +140,7 @@ // the frame size used for data expansion is 64 bytes. // See the definition of the macro LOAD1 above (4 bytes * 16 entries). // -//func block(dig *digest, p []byte) +//func block(dig *Digest, p []byte) TEXT ·block(SB),NOSPLIT,$64-32 MOVV p_base+8(FP), R5 MOVV p_len+16(FP), R6 diff --git a/crypto/sha256/sha256block_generic.go b/crypto/internal/fips140/sha256/sha256block_noasm.go similarity index 89% rename from crypto/sha256/sha256block_generic.go rename to crypto/internal/fips140/sha256/sha256block_noasm.go index 8ca8401f65a..cc7abf6a382 100644 --- a/crypto/sha256/sha256block_generic.go +++ b/crypto/internal/fips140/sha256/sha256block_noasm.go @@ -6,6 +6,6 @@ package sha256 -func block(dig *digest, p []byte) { +func block(dig *Digest, p []byte) { blockGeneric(dig, p) } diff --git a/crypto/internal/fips140/sha256/sha256block_ppc64x.go b/crypto/internal/fips140/sha256/sha256block_ppc64x.go new file mode 100644 index 00000000000..882e35f1b82 --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256block_ppc64x.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64 || ppc64le) && !purego + +package sha256 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// The POWER architecture doesn't have a way to turn off SHA-2 support at +// runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG knob for +// that. It's intentionally only checked at init() time, to avoid the +// performance overhead of checking it on every block. +var ppc64sha2 = godebug.Value("#ppc64sha2") != "off" + +func init() { + impl.Register("sha256", "POWER8", &ppc64sha2) +} + +//go:noescape +func blockPOWER(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if ppc64sha2 { + blockPOWER(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha256/sha256block_ppc64x.s b/crypto/internal/fips140/sha256/sha256block_ppc64x.s similarity index 99% rename from crypto/sha256/sha256block_ppc64x.s rename to crypto/internal/fips140/sha256/sha256block_ppc64x.s index ba8fa623c11..b28f80dcfa2 100644 --- a/crypto/sha256/sha256block_ppc64x.s +++ b/crypto/internal/fips140/sha256/sha256block_ppc64x.s @@ -284,8 +284,8 @@ GLOBL ·kcon(SB), RODATA, $1088 #define VPERMLE(va,vb,vc,vt) #endif -// func block(dig *digest, p []byte) -TEXT ·block(SB),0,$0-32 +// func blockPOWER(dig *Digest, p []byte) +TEXT ·blockPOWER(SB),0,$0-32 MOVD dig+0(FP), CTX MOVD p_base+8(FP), INP MOVD p_len+16(FP), LEN diff --git a/crypto/sha256/sha256block_riscv64.s b/crypto/internal/fips140/sha256/sha256block_riscv64.s similarity index 96% rename from crypto/sha256/sha256block_riscv64.s rename to crypto/internal/fips140/sha256/sha256block_riscv64.s index f31bfb8d53d..567d44781cb 100644 --- a/crypto/sha256/sha256block_riscv64.s +++ b/crypto/internal/fips140/sha256/sha256block_riscv64.s @@ -88,47 +88,46 @@ // T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt // BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) // Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +// = ((y XOR z) AND x) XOR z #define SHA256T1(index, e, f, g, h) \ MOVWU (index*4)(X18), X8; \ ADD X5, h; \ RORW $6, e, X6; \ ADD X8, h; \ RORW $11, e, X7; \ - XOR X7, X6; \ RORW $25, e, X8; \ + XOR X7, X6; \ + XOR f, g, X5; \ XOR X8, X6; \ + AND e, X5; \ ADD X6, h; \ - AND e, f, X5; \ - NOT e, X7; \ - AND g, X7; \ - XOR X7, X5; \ + XOR g, X5; \ ADD h, X5 // Calculate T2 in X6. // T2 = BIGSIGMA0(a) + Maj(a, b, c) // BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) // Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +// = ((y XOR z) AND x) XOR (y AND z) #define SHA256T2(a, b, c) \ RORW $2, a, X6; \ RORW $13, a, X7; \ - XOR X7, X6; \ RORW $22, a, X8; \ + XOR X7, X6; \ + XOR b, c, X9; \ + AND b, c, X7; \ + AND a, X9; \ XOR X8, X6; \ - AND a, b, X7; \ - AND a, c, X8; \ - XOR X8, X7; \ - AND b, c, X9; \ - XOR X9, X7; \ - ADD X7, X6 + XOR X7, X9; \ + ADD X9, X6 // Calculate T1 and T2, then e = d + T1 and a = T1 + T2. // The values for e and a are stored in d and h, ready for rotation. #define SHA256ROUND(index, a, b, c, d, e, f, g, h) \ SHA256T1(index, e, f, g, h); \ SHA256T2(a, b, c); \ - MOV X6, h; \ ADD X5, d; \ - ADD X5, h + ADD X6, X5, h #define SHA256ROUND0(index, a, b, c, d, e, f, g, h) \ MSGSCHEDULE0(index); \ @@ -141,7 +140,7 @@ // Note that 64 bytes of stack space is used as a circular buffer // for the message schedule (4 bytes * 16 entries). // -// func block(dig *digest, p []byte) +// func block(dig *Digest, p []byte) TEXT ·block(SB),0,$64-32 MOV p_base+8(FP), X29 MOV p_len+16(FP), X30 @@ -151,7 +150,7 @@ TEXT ·block(SB),0,$64-32 ADD X29, X30, X28 BEQ X28, X29, end - MOV ·_K(SB), X18 // const table + MOV $·_K(SB), X18 // const table ADD $8, X2, X19 // message schedule MOV dig+0(FP), X20 diff --git a/crypto/internal/fips140/sha256/sha256block_s390x.go b/crypto/internal/fips140/sha256/sha256block_s390x.go new file mode 100644 index 00000000000..b2f22f80049 --- /dev/null +++ b/crypto/internal/fips140/sha256/sha256block_s390x.go @@ -0,0 +1,31 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha256 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useSHA256 = cpu.S390XHasSHA256 + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf + impl.Register("sha256", "CPACF", &useSHA256) +} + +//go:noescape +func blockS390X(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useSHA256 { + blockS390X(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha256/sha256block_s390x.s b/crypto/internal/fips140/sha256/sha256block_s390x.s similarity index 73% rename from crypto/sha256/sha256block_s390x.s rename to crypto/internal/fips140/sha256/sha256block_s390x.s index 757d62f5125..06469d68d65 100644 --- a/crypto/sha256/sha256block_s390x.s +++ b/crypto/internal/fips140/sha256/sha256block_s390x.s @@ -6,17 +6,12 @@ #include "textflag.h" -// func block(dig *digest, p []byte) -TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 - MOVBZ ·useAsm(SB), R4 +// func blockS390X(dig *Digest, p []byte) +TEXT ·blockS390X(SB), NOSPLIT|NOFRAME, $0-32 LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) MOVBZ $2, R0 // SHA-256 function code - CMPBEQ R4, $0, generic loop: KIMD R0, R2 // compute intermediate message digest (KIMD) BVS loop // continue if interrupted RET - -generic: - BR ·blockGeneric(SB) diff --git a/crypto/internal/fips140/sha3/_asm/go.mod b/crypto/internal/fips140/sha3/_asm/go.mod new file mode 100644 index 00000000000..39e83acc943 --- /dev/null +++ b/crypto/internal/fips140/sha3/_asm/go.mod @@ -0,0 +1,11 @@ +module sha3/_asm + +go 1.22 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.19.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/tools v0.23.0 // indirect +) diff --git a/crypto/internal/fips140/sha3/_asm/go.sum b/crypto/internal/fips140/sha3/_asm/go.sum new file mode 100644 index 00000000000..9e8f35f70fc --- /dev/null +++ b/crypto/internal/fips140/sha3/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= diff --git a/crypto/internal/fips140/sha3/_asm/keccakf_amd64_asm.go b/crypto/internal/fips140/sha3/_asm/keccakf_amd64_asm.go new file mode 100644 index 00000000000..5e59b11fc87 --- /dev/null +++ b/crypto/internal/fips140/sha3/_asm/keccakf_amd64_asm.go @@ -0,0 +1,443 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources at https://github.com/gvanas/KeccakCodePackage + +package main + +import ( + "os" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +//go:generate go run . -out ../sha3_amd64.s + +// Round Constants for use in the ι step. +var RoundConstants = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} + +var ( + // Temporary registers + rT1 GPPhysical = RAX + + // Round vars + rpState = Mem{Base: RDI} + rpStack = Mem{Base: RSP} + + rDa = RBX + rDe = RCX + rDi = RDX + rDo = R8 + rDu = R9 + + rBa = R10 + rBe = R11 + rBi = R12 + rBo = R13 + rBu = R14 + + rCa = RSI + rCe = RBP + rCi = rBi + rCo = rBo + rCu = R15 +) + +const ( + _ba = iota * 8 + _be + _bi + _bo + _bu + _ga + _ge + _gi + _go + _gu + _ka + _ke + _ki + _ko + _ku + _ma + _me + _mi + _mo + _mu + _sa + _se + _si + _so + _su +) + +func main() { + // https://github.com/mmcloughlin/avo/issues/450 + os.Setenv("GOOS", "linux") + os.Setenv("GOARCH", "amd64") + + Package("crypto/internal/fips140/sha3") + ConstraintExpr("!purego") + keccakF1600() + Generate() +} + +func MOVQ_RBI_RCE() { MOVQ(rBi, rCe) } +func XORQ_RT1_RCA() { XORQ(rT1, rCa) } +func XORQ_RT1_RCE() { XORQ(rT1, rCe) } +func XORQ_RBA_RCU() { XORQ(rBa, rCu) } +func XORQ_RBE_RCU() { XORQ(rBe, rCu) } +func XORQ_RDU_RCU() { XORQ(rDu, rCu) } +func XORQ_RDA_RCA() { XORQ(rDa, rCa) } +func XORQ_RDE_RCE() { XORQ(rDe, rCe) } + +type ArgMacro func() + +func mKeccakRound( + iState, oState Mem, + rc U64, + B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, + K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, + M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, + S_RDE_RCE ArgMacro, +) { + Comment("Prepare round") + MOVQ(rCe, rDa) + ROLQ(Imm(1), rDa) + + MOVQ(iState.Offset(_bi), rCi) + XORQ(iState.Offset(_gi), rDi) + XORQ(rCu, rDa) + XORQ(iState.Offset(_ki), rCi) + XORQ(iState.Offset(_mi), rDi) + XORQ(rDi, rCi) + + MOVQ(rCi, rDe) + ROLQ(Imm(1), rDe) + + MOVQ(iState.Offset(_bo), rCo) + XORQ(iState.Offset(_go), rDo) + XORQ(rCa, rDe) + XORQ(iState.Offset(_ko), rCo) + XORQ(iState.Offset(_mo), rDo) + XORQ(rDo, rCo) + + MOVQ(rCo, rDi) + ROLQ(Imm(1), rDi) + + MOVQ(rCu, rDo) + XORQ(rCe, rDi) + ROLQ(Imm(1), rDo) + + MOVQ(rCa, rDu) + XORQ(rCi, rDo) + ROLQ(Imm(1), rDu) + + Comment("Result b") + MOVQ(iState.Offset(_ba), rBa) + MOVQ(iState.Offset(_ge), rBe) + XORQ(rCo, rDu) + MOVQ(iState.Offset(_ki), rBi) + MOVQ(iState.Offset(_mo), rBo) + MOVQ(iState.Offset(_su), rBu) + XORQ(rDe, rBe) + ROLQ(Imm(44), rBe) + XORQ(rDi, rBi) + XORQ(rDa, rBa) + ROLQ(Imm(43), rBi) + + MOVQ(rBe, rCa) + MOVQ(rc, rT1) + ORQ(rBi, rCa) + XORQ(rBa, rT1) + XORQ(rT1, rCa) + MOVQ(rCa, oState.Offset(_ba)) + + XORQ(rDu, rBu) + ROLQ(Imm(14), rBu) + MOVQ(rBa, rCu) + ANDQ(rBe, rCu) + XORQ(rBu, rCu) + MOVQ(rCu, oState.Offset(_bu)) + + XORQ(rDo, rBo) + ROLQ(Imm(21), rBo) + MOVQ(rBo, rT1) + ANDQ(rBu, rT1) + XORQ(rBi, rT1) + MOVQ(rT1, oState.Offset(_bi)) + + NOTQ(rBi) + ORQ(rBa, rBu) + ORQ(rBo, rBi) + XORQ(rBo, rBu) + XORQ(rBe, rBi) + MOVQ(rBu, oState.Offset(_bo)) + MOVQ(rBi, oState.Offset(_be)) + B_RBI_RCE() + + Comment("Result g") + MOVQ(iState.Offset(_gu), rBe) + XORQ(rDu, rBe) + MOVQ(iState.Offset(_ka), rBi) + ROLQ(Imm(20), rBe) + XORQ(rDa, rBi) + ROLQ(Imm(3), rBi) + MOVQ(iState.Offset(_bo), rBa) + MOVQ(rBe, rT1) + ORQ(rBi, rT1) + XORQ(rDo, rBa) + MOVQ(iState.Offset(_me), rBo) + MOVQ(iState.Offset(_si), rBu) + ROLQ(Imm(28), rBa) + XORQ(rBa, rT1) + MOVQ(rT1, oState.Offset(_ga)) + G_RT1_RCA() + + XORQ(rDe, rBo) + ROLQ(Imm(45), rBo) + MOVQ(rBi, rT1) + ANDQ(rBo, rT1) + XORQ(rBe, rT1) + MOVQ(rT1, oState.Offset(_ge)) + G_RT1_RCE() + + XORQ(rDi, rBu) + ROLQ(Imm(61), rBu) + MOVQ(rBu, rT1) + ORQ(rBa, rT1) + XORQ(rBo, rT1) + MOVQ(rT1, oState.Offset(_go)) + + ANDQ(rBe, rBa) + XORQ(rBu, rBa) + MOVQ(rBa, oState.Offset(_gu)) + NOTQ(rBu) + G_RBA_RCU() + + ORQ(rBu, rBo) + XORQ(rBi, rBo) + MOVQ(rBo, oState.Offset(_gi)) + + Comment("Result k") + MOVQ(iState.Offset(_be), rBa) + MOVQ(iState.Offset(_gi), rBe) + MOVQ(iState.Offset(_ko), rBi) + MOVQ(iState.Offset(_mu), rBo) + MOVQ(iState.Offset(_sa), rBu) + XORQ(rDi, rBe) + ROLQ(Imm(6), rBe) + XORQ(rDo, rBi) + ROLQ(Imm(25), rBi) + MOVQ(rBe, rT1) + ORQ(rBi, rT1) + XORQ(rDe, rBa) + ROLQ(Imm(1), rBa) + XORQ(rBa, rT1) + MOVQ(rT1, oState.Offset(_ka)) + K_RT1_RCA() + + XORQ(rDu, rBo) + ROLQ(Imm(8), rBo) + MOVQ(rBi, rT1) + ANDQ(rBo, rT1) + XORQ(rBe, rT1) + MOVQ(rT1, oState.Offset(_ke)) + K_RT1_RCE() + + XORQ(rDa, rBu) + ROLQ(Imm(18), rBu) + NOTQ(rBo) + MOVQ(rBo, rT1) + ANDQ(rBu, rT1) + XORQ(rBi, rT1) + MOVQ(rT1, oState.Offset(_ki)) + + MOVQ(rBu, rT1) + ORQ(rBa, rT1) + XORQ(rBo, rT1) + MOVQ(rT1, oState.Offset(_ko)) + + ANDQ(rBe, rBa) + XORQ(rBu, rBa) + MOVQ(rBa, oState.Offset(_ku)) + K_RBA_RCU() + + Comment("Result m") + MOVQ(iState.Offset(_ga), rBe) + XORQ(rDa, rBe) + MOVQ(iState.Offset(_ke), rBi) + ROLQ(Imm(36), rBe) + XORQ(rDe, rBi) + MOVQ(iState.Offset(_bu), rBa) + ROLQ(Imm(10), rBi) + MOVQ(rBe, rT1) + MOVQ(iState.Offset(_mi), rBo) + ANDQ(rBi, rT1) + XORQ(rDu, rBa) + MOVQ(iState.Offset(_so), rBu) + ROLQ(Imm(27), rBa) + XORQ(rBa, rT1) + MOVQ(rT1, oState.Offset(_ma)) + M_RT1_RCA() + + XORQ(rDi, rBo) + ROLQ(Imm(15), rBo) + MOVQ(rBi, rT1) + ORQ(rBo, rT1) + XORQ(rBe, rT1) + MOVQ(rT1, oState.Offset(_me)) + M_RT1_RCE() + + XORQ(rDo, rBu) + ROLQ(Imm(56), rBu) + NOTQ(rBo) + MOVQ(rBo, rT1) + ORQ(rBu, rT1) + XORQ(rBi, rT1) + MOVQ(rT1, oState.Offset(_mi)) + + ORQ(rBa, rBe) + XORQ(rBu, rBe) + MOVQ(rBe, oState.Offset(_mu)) + + ANDQ(rBa, rBu) + XORQ(rBo, rBu) + MOVQ(rBu, oState.Offset(_mo)) + M_RBE_RCU() + + Comment("Result s") + MOVQ(iState.Offset(_bi), rBa) + MOVQ(iState.Offset(_go), rBe) + MOVQ(iState.Offset(_ku), rBi) + XORQ(rDi, rBa) + MOVQ(iState.Offset(_ma), rBo) + ROLQ(Imm(62), rBa) + XORQ(rDo, rBe) + MOVQ(iState.Offset(_se), rBu) + ROLQ(Imm(55), rBe) + + XORQ(rDu, rBi) + MOVQ(rBa, rDu) + XORQ(rDe, rBu) + ROLQ(Imm(2), rBu) + ANDQ(rBe, rDu) + XORQ(rBu, rDu) + MOVQ(rDu, oState.Offset(_su)) + + ROLQ(Imm(39), rBi) + S_RDU_RCU() + NOTQ(rBe) + XORQ(rDa, rBo) + MOVQ(rBe, rDa) + ANDQ(rBi, rDa) + XORQ(rBa, rDa) + MOVQ(rDa, oState.Offset(_sa)) + S_RDA_RCA() + + ROLQ(Imm(41), rBo) + MOVQ(rBi, rDe) + ORQ(rBo, rDe) + XORQ(rBe, rDe) + MOVQ(rDe, oState.Offset(_se)) + S_RDE_RCE() + + MOVQ(rBo, rDi) + MOVQ(rBu, rDo) + ANDQ(rBu, rDi) + ORQ(rBa, rDo) + XORQ(rBi, rDi) + XORQ(rBo, rDo) + MOVQ(rDi, oState.Offset(_si)) + MOVQ(rDo, oState.Offset(_so)) +} + +// keccakF1600 applies the Keccak permutation to a 1600b-wide +// state represented as a slice of 25 uint64s. +func keccakF1600() { + Implement("keccakF1600") + AllocLocal(200) + + Load(Param("a"), rpState.Base) + + Comment("Convert the user state into an internal state") + NOTQ(rpState.Offset(_be)) + NOTQ(rpState.Offset(_bi)) + NOTQ(rpState.Offset(_go)) + NOTQ(rpState.Offset(_ki)) + NOTQ(rpState.Offset(_mi)) + NOTQ(rpState.Offset(_sa)) + + Comment("Execute the KeccakF permutation") + MOVQ(rpState.Offset(_ba), rCa) + MOVQ(rpState.Offset(_be), rCe) + MOVQ(rpState.Offset(_bu), rCu) + + XORQ(rpState.Offset(_ga), rCa) + XORQ(rpState.Offset(_ge), rCe) + XORQ(rpState.Offset(_gu), rCu) + + XORQ(rpState.Offset(_ka), rCa) + XORQ(rpState.Offset(_ke), rCe) + XORQ(rpState.Offset(_ku), rCu) + + XORQ(rpState.Offset(_ma), rCa) + XORQ(rpState.Offset(_me), rCe) + XORQ(rpState.Offset(_mu), rCu) + + XORQ(rpState.Offset(_sa), rCa) + XORQ(rpState.Offset(_se), rCe) + MOVQ(rpState.Offset(_si), rDi) + MOVQ(rpState.Offset(_so), rDo) + XORQ(rpState.Offset(_su), rCu) + + for i, rc := range RoundConstants[:len(RoundConstants)-1] { + var iState, oState Mem + if i%2 == 0 { + iState, oState = rpState, rpStack + } else { + iState, oState = rpStack, rpState + } + mKeccakRound(iState, oState, U64(rc), MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + } + mKeccakRound(rpStack, rpState, U64(RoundConstants[len(RoundConstants)-1]), NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) + + Comment("Revert the internal state to the user state") + NOTQ(rpState.Offset(_be)) + NOTQ(rpState.Offset(_bi)) + NOTQ(rpState.Offset(_go)) + NOTQ(rpState.Offset(_ki)) + NOTQ(rpState.Offset(_mi)) + NOTQ(rpState.Offset(_sa)) + + RET() +} diff --git a/crypto/internal/fips140/sha3/cast.go b/crypto/internal/fips140/sha3/cast.go new file mode 100644 index 00000000000..2ac6d4a3ecb --- /dev/null +++ b/crypto/internal/fips140/sha3/cast.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + fips140.CAST("cSHAKE128", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0xd2, 0x17, 0x37, 0x39, 0xf6, 0xa1, 0xe4, 0x6e, + 0x81, 0xe5, 0x70, 0xe3, 0x1b, 0x10, 0x4c, 0x82, + 0xc5, 0x48, 0xee, 0xe6, 0x09, 0xf5, 0x89, 0x52, + 0x52, 0xa4, 0x69, 0xd4, 0xd0, 0x76, 0x68, 0x6b, + } + h := NewCShake128(input, input) + h.Write(input) + if got := h.Sum(nil); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/sha3/hashes.go b/crypto/internal/fips140/sha3/hashes.go new file mode 100644 index 00000000000..da1b9bcf5f8 --- /dev/null +++ b/crypto/internal/fips140/sha3/hashes.go @@ -0,0 +1,59 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +// New224 returns a new Digest computing the SHA3-224 hash. +func New224() *Digest { + return &Digest{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3} +} + +// New256 returns a new Digest computing the SHA3-256 hash. +func New256() *Digest { + return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3} +} + +// New384 returns a new Digest computing the SHA3-384 hash. +func New384() *Digest { + return &Digest{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3} +} + +// New512 returns a new Digest computing the SHA3-512 hash. +func New512() *Digest { + return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3} +} + +// TODO(fips): do this in the stdlib crypto/sha3 package. +// +// crypto.RegisterHash(crypto.SHA3_224, New224) +// crypto.RegisterHash(crypto.SHA3_256, New256) +// crypto.RegisterHash(crypto.SHA3_384, New384) +// crypto.RegisterHash(crypto.SHA3_512, New512) + +const ( + dsbyteSHA3 = 0b00000110 + dsbyteKeccak = 0b00000001 + dsbyteShake = 0b00011111 + dsbyteCShake = 0b00000100 + + // rateK[c] is the rate in bytes for Keccak[c] where c is the capacity in + // bits. Given the sponge size is 1600 bits, the rate is 1600 - c bits. + rateK256 = (1600 - 256) / 8 + rateK448 = (1600 - 448) / 8 + rateK512 = (1600 - 512) / 8 + rateK768 = (1600 - 768) / 8 + rateK1024 = (1600 - 1024) / 8 +) + +// NewLegacyKeccak256 returns a new Digest computing the legacy, non-standard +// Keccak-256 hash. +func NewLegacyKeccak256() *Digest { + return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak} +} + +// NewLegacyKeccak512 returns a new Digest computing the legacy, non-standard +// Keccak-512 hash. +func NewLegacyKeccak512() *Digest { + return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak} +} diff --git a/crypto/internal/fips140/sha3/keccakf.go b/crypto/internal/fips140/sha3/keccakf.go new file mode 100644 index 00000000000..0d9e764b465 --- /dev/null +++ b/crypto/internal/fips140/sha3/keccakf.go @@ -0,0 +1,432 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +import ( + "math/bits" + "unsafe" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" +) + +// rc stores the round constants for use in the ι step. +var rc = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} + +// keccakF1600Generic applies the Keccak permutation. +func keccakF1600Generic(da *[200]byte) { + var a *[25]uint64 + if cpu.BigEndian { + a = new([25]uint64) + for i := range a { + a[i] = byteorder.LEUint64(da[i*8:]) + } + defer func() { + for i := range a { + byteorder.LEPutUint64(da[i*8:], a[i]) + } + }() + } else { + a = (*[25]uint64)(unsafe.Pointer(da)) + } + + // Implementation translated from Keccak-inplace.c + // in the keccak reference code. + var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 + + for i := 0; i < 24; i += 4 { + // Combines the 5 steps in each round into 2 steps. + // Unrolls 4 rounds per loop and spreads some steps across rounds. + + // Round 1 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[6] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[12] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[18] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[24] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] + a[6] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[16] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[22] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[3] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[10] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[1] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[7] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[19] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[20] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[11] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[23] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[4] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[5] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[2] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[8] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[14] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[15] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + // Round 2 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[16] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[7] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[23] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[14] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] + a[16] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[11] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[2] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[18] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[20] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[6] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[22] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[4] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[15] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[1] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[8] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[24] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[10] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[12] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[3] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[19] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[5] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + // Round 3 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[11] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[22] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[8] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[19] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] + a[11] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[1] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[12] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[23] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[15] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[16] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[2] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[24] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[5] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[6] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[3] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[14] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[20] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[7] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[18] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[4] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[10] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + // Round 4 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[1] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[2] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[3] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[4] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] + a[1] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[6] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[7] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[8] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[5] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[11] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[12] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[14] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[10] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[16] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[18] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[19] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[15] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[22] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[23] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[24] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[20] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + } +} diff --git a/crypto/internal/fips140/sha3/sha3.go b/crypto/internal/fips140/sha3/sha3.go new file mode 100644 index 00000000000..4ac17655247 --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3.go @@ -0,0 +1,236 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha3 implements the SHA-3 fixed-output-length hash functions and +// the SHAKE variable-output-length functions defined by [FIPS 202], as well as +// the cSHAKE extendable-output-length functions defined by [SP 800-185]. +// +// [FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202 +// [SP 800-185]: https://doi.org/10.6028/NIST.SP.800-185 +package sha3 + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" +) + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +type Digest struct { + a [1600 / 8]byte // main state of the hash + + // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR + // into before running the permutation. If squeezing, it's the remaining + // output to produce before running the permutation. + n, rate int + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *Digest) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *Digest) Size() int { return d.outputLen } + +// Reset resets the Digest to its initial state. +func (d *Digest) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.n = 0 +} + +func (d *Digest) Clone() *Digest { + ret := *d + return &ret +} + +// permute applies the KeccakF-1600 permutation. +func (d *Digest) permute() { + keccakF1600(&d.a) + d.n = 0 +} + +// padAndPermute appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *Digest) padAndPermute() { + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in the sponge because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + d.a[d.n] ^= d.dsbyte + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + d.a[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing +} + +// Write absorbs more data into the hash's state. +func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) } +func (d *Digest) writeGeneric(p []byte) (n int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: Write after Read") + } + + n = len(p) + + for len(p) > 0 { + x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) + d.n += x + p = p[x:] + + // If the sponge is full, apply the permutation. + if d.n == d.rate { + d.permute() + } + } + + return +} + +// read squeezes an arbitrary number of bytes from the sponge. +func (d *Digest) readGeneric(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute() + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + // Apply the permutation if we've squeezed the sponge dry. + if d.n == d.rate { + d.permute() + } + + x := copy(out, d.a[d.n:d.rate]) + d.n += x + out = out[x:] + } + + return +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (d *Digest) Sum(b []byte) []byte { + fips140.RecordApproved() + return d.sum(b) +} + +func (d *Digest) sumGeneric(b []byte) []byte { + if d.state != spongeAbsorbing { + panic("sha3: Sum after Read") + } + + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.Clone() + hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation + dup.read(hash) + return append(b, hash...) +} + +const ( + magicSHA3 = "sha\x08" + magicShake = "sha\x09" + magicCShake = "sha\x0a" + magicKeccak = "sha\x0b" + // magic || rate || main state || n || sponge direction + marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1 +) + +func (d *Digest) MarshalBinary() ([]byte, error) { + return d.AppendBinary(make([]byte, 0, marshaledSize)) +} + +func (d *Digest) AppendBinary(b []byte) ([]byte, error) { + switch d.dsbyte { + case dsbyteSHA3: + b = append(b, magicSHA3...) + case dsbyteShake: + b = append(b, magicShake...) + case dsbyteCShake: + b = append(b, magicCShake...) + case dsbyteKeccak: + b = append(b, magicKeccak...) + default: + panic("unknown dsbyte") + } + // rate is at most 168, and n is at most rate. + b = append(b, byte(d.rate)) + b = append(b, d.a[:]...) + b = append(b, byte(d.n), byte(d.state)) + return b, nil +} + +func (d *Digest) UnmarshalBinary(b []byte) error { + if len(b) != marshaledSize { + return errors.New("sha3: invalid hash state") + } + + magic := string(b[:len(magicSHA3)]) + b = b[len(magicSHA3):] + switch { + case magic == magicSHA3 && d.dsbyte == dsbyteSHA3: + case magic == magicShake && d.dsbyte == dsbyteShake: + case magic == magicCShake && d.dsbyte == dsbyteCShake: + case magic == magicKeccak && d.dsbyte == dsbyteKeccak: + default: + return errors.New("sha3: invalid hash state identifier") + } + + rate := int(b[0]) + b = b[1:] + if rate != d.rate { + return errors.New("sha3: invalid hash state function") + } + + copy(d.a[:], b) + b = b[len(d.a):] + + n, state := int(b[0]), spongeDirection(b[1]) + if n > d.rate { + return errors.New("sha3: invalid hash state") + } + d.n = n + if state != spongeAbsorbing && state != spongeSqueezing { + return errors.New("sha3: invalid hash state") + } + d.state = state + + return nil +} diff --git a/crypto/internal/fips140/sha3/sha3_amd64.go b/crypto/internal/fips140/sha3/sha3_amd64.go new file mode 100644 index 00000000000..d986e3f7b32 --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_amd64.go @@ -0,0 +1,20 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha3 + +//go:noescape +func keccakF1600(a *[200]byte) + +func (d *Digest) write(p []byte) (n int, err error) { + return d.writeGeneric(p) +} +func (d *Digest) read(out []byte) (n int, err error) { + return d.readGeneric(out) +} +func (d *Digest) sum(b []byte) []byte { + return d.sumGeneric(b) +} diff --git a/crypto/internal/fips140/sha3/sha3_amd64.s b/crypto/internal/fips140/sha3/sha3_amd64.s new file mode 100644 index 00000000000..3137e2d6cfa --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_amd64.s @@ -0,0 +1,5419 @@ +// Code generated by command: go run keccakf_amd64_asm.go -out ../sha3_amd64.s. DO NOT EDIT. + +//go:build !purego + +// func keccakF1600(a *[200]byte) +TEXT ·keccakF1600(SB), $200-8 + MOVQ a+0(FP), DI + + // Convert the user state into an internal state + NOTQ 8(DI) + NOTQ 16(DI) + NOTQ 64(DI) + NOTQ 96(DI) + NOTQ 136(DI) + NOTQ 160(DI) + + // Execute the KeccakF permutation + MOVQ (DI), SI + MOVQ 8(DI), BP + MOVQ 32(DI), R15 + XORQ 40(DI), SI + XORQ 48(DI), BP + XORQ 72(DI), R15 + XORQ 80(DI), SI + XORQ 88(DI), BP + XORQ 112(DI), R15 + XORQ 120(DI), SI + XORQ 128(DI), BP + XORQ 152(DI), R15 + XORQ 160(DI), SI + XORQ 168(DI), BP + MOVQ 176(DI), DX + MOVQ 184(DI), R8 + XORQ 192(DI), R15 + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000000000001, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000000008082, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x800000000000808a, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000080008000, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x000000000000808b, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000080000001, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000080008081, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000008009, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x000000000000008a, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000000000088, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000080008009, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x000000008000000a, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x000000008000808b, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x800000000000008b, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000008089, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000008003, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000008002, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000000080, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x000000000000800a, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x800000008000000a, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000080008081, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000000008080, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + MOVQ R12, BP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + XORQ R10, R15 + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + XORQ R11, R15 + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(DI), R12 + XORQ 56(DI), DX + XORQ R15, BX + XORQ 96(DI), R12 + XORQ 136(DI), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(DI), R13 + XORQ 64(DI), R8 + XORQ SI, CX + XORQ 104(DI), R13 + XORQ 144(DI), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (DI), R10 + MOVQ 48(DI), R11 + XORQ R13, R9 + MOVQ 96(DI), R12 + MOVQ 144(DI), R13 + MOVQ 192(DI), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x0000000080000001, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (SP) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(SP) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(SP) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(SP) + MOVQ R12, 8(SP) + MOVQ R12, BP + + // Result g + MOVQ 72(DI), R11 + XORQ R9, R11 + MOVQ 80(DI), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(DI), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(DI), R13 + MOVQ 176(DI), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(SP) + XORQ AX, SI + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(SP) + XORQ AX, BP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(SP) + NOTQ R14 + XORQ R10, R15 + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(SP) + + // Result k + MOVQ 8(DI), R10 + MOVQ 56(DI), R11 + MOVQ 104(DI), R12 + MOVQ 152(DI), R13 + MOVQ 160(DI), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(SP) + XORQ AX, SI + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(SP) + XORQ AX, BP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(SP) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(SP) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(SP) + XORQ R10, R15 + + // Result m + MOVQ 40(DI), R11 + XORQ BX, R11 + MOVQ 88(DI), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(DI), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(DI), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(DI), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(SP) + XORQ AX, SI + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(SP) + XORQ AX, BP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(SP) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(SP) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(SP) + XORQ R11, R15 + + // Result s + MOVQ 16(DI), R10 + MOVQ 64(DI), R11 + MOVQ 112(DI), R12 + XORQ DX, R10 + MOVQ 120(DI), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(DI), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(SP) + ROLQ $0x27, R12 + XORQ R9, R15 + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(SP) + XORQ BX, SI + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(SP) + XORQ CX, BP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(SP) + MOVQ R8, 184(SP) + + // Prepare round + MOVQ BP, BX + ROLQ $0x01, BX + MOVQ 16(SP), R12 + XORQ 56(SP), DX + XORQ R15, BX + XORQ 96(SP), R12 + XORQ 136(SP), DX + XORQ DX, R12 + MOVQ R12, CX + ROLQ $0x01, CX + MOVQ 24(SP), R13 + XORQ 64(SP), R8 + XORQ SI, CX + XORQ 104(SP), R13 + XORQ 144(SP), R8 + XORQ R8, R13 + MOVQ R13, DX + ROLQ $0x01, DX + MOVQ R15, R8 + XORQ BP, DX + ROLQ $0x01, R8 + MOVQ SI, R9 + XORQ R12, R8 + ROLQ $0x01, R9 + + // Result b + MOVQ (SP), R10 + MOVQ 48(SP), R11 + XORQ R13, R9 + MOVQ 96(SP), R12 + MOVQ 144(SP), R13 + MOVQ 192(SP), R14 + XORQ CX, R11 + ROLQ $0x2c, R11 + XORQ DX, R12 + XORQ BX, R10 + ROLQ $0x2b, R12 + MOVQ R11, SI + MOVQ $0x8000000080008008, AX + ORQ R12, SI + XORQ R10, AX + XORQ AX, SI + MOVQ SI, (DI) + XORQ R9, R14 + ROLQ $0x0e, R14 + MOVQ R10, R15 + ANDQ R11, R15 + XORQ R14, R15 + MOVQ R15, 32(DI) + XORQ R8, R13 + ROLQ $0x15, R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 16(DI) + NOTQ R12 + ORQ R10, R14 + ORQ R13, R12 + XORQ R13, R14 + XORQ R11, R12 + MOVQ R14, 24(DI) + MOVQ R12, 8(DI) + NOP + + // Result g + MOVQ 72(SP), R11 + XORQ R9, R11 + MOVQ 80(SP), R12 + ROLQ $0x14, R11 + XORQ BX, R12 + ROLQ $0x03, R12 + MOVQ 24(SP), R10 + MOVQ R11, AX + ORQ R12, AX + XORQ R8, R10 + MOVQ 128(SP), R13 + MOVQ 176(SP), R14 + ROLQ $0x1c, R10 + XORQ R10, AX + MOVQ AX, 40(DI) + NOP + XORQ CX, R13 + ROLQ $0x2d, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 48(DI) + NOP + XORQ DX, R14 + ROLQ $0x3d, R14 + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 64(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 72(DI) + NOTQ R14 + NOP + ORQ R14, R13 + XORQ R12, R13 + MOVQ R13, 56(DI) + + // Result k + MOVQ 8(SP), R10 + MOVQ 56(SP), R11 + MOVQ 104(SP), R12 + MOVQ 152(SP), R13 + MOVQ 160(SP), R14 + XORQ DX, R11 + ROLQ $0x06, R11 + XORQ R8, R12 + ROLQ $0x19, R12 + MOVQ R11, AX + ORQ R12, AX + XORQ CX, R10 + ROLQ $0x01, R10 + XORQ R10, AX + MOVQ AX, 80(DI) + NOP + XORQ R9, R13 + ROLQ $0x08, R13 + MOVQ R12, AX + ANDQ R13, AX + XORQ R11, AX + MOVQ AX, 88(DI) + NOP + XORQ BX, R14 + ROLQ $0x12, R14 + NOTQ R13 + MOVQ R13, AX + ANDQ R14, AX + XORQ R12, AX + MOVQ AX, 96(DI) + MOVQ R14, AX + ORQ R10, AX + XORQ R13, AX + MOVQ AX, 104(DI) + ANDQ R11, R10 + XORQ R14, R10 + MOVQ R10, 112(DI) + NOP + + // Result m + MOVQ 40(SP), R11 + XORQ BX, R11 + MOVQ 88(SP), R12 + ROLQ $0x24, R11 + XORQ CX, R12 + MOVQ 32(SP), R10 + ROLQ $0x0a, R12 + MOVQ R11, AX + MOVQ 136(SP), R13 + ANDQ R12, AX + XORQ R9, R10 + MOVQ 184(SP), R14 + ROLQ $0x1b, R10 + XORQ R10, AX + MOVQ AX, 120(DI) + NOP + XORQ DX, R13 + ROLQ $0x0f, R13 + MOVQ R12, AX + ORQ R13, AX + XORQ R11, AX + MOVQ AX, 128(DI) + NOP + XORQ R8, R14 + ROLQ $0x38, R14 + NOTQ R13 + MOVQ R13, AX + ORQ R14, AX + XORQ R12, AX + MOVQ AX, 136(DI) + ORQ R10, R11 + XORQ R14, R11 + MOVQ R11, 152(DI) + ANDQ R10, R14 + XORQ R13, R14 + MOVQ R14, 144(DI) + NOP + + // Result s + MOVQ 16(SP), R10 + MOVQ 64(SP), R11 + MOVQ 112(SP), R12 + XORQ DX, R10 + MOVQ 120(SP), R13 + ROLQ $0x3e, R10 + XORQ R8, R11 + MOVQ 168(SP), R14 + ROLQ $0x37, R11 + XORQ R9, R12 + MOVQ R10, R9 + XORQ CX, R14 + ROLQ $0x02, R14 + ANDQ R11, R9 + XORQ R14, R9 + MOVQ R9, 192(DI) + ROLQ $0x27, R12 + NOP + NOTQ R11 + XORQ BX, R13 + MOVQ R11, BX + ANDQ R12, BX + XORQ R10, BX + MOVQ BX, 160(DI) + NOP + ROLQ $0x29, R13 + MOVQ R12, CX + ORQ R13, CX + XORQ R11, CX + MOVQ CX, 168(DI) + NOP + MOVQ R13, DX + MOVQ R14, R8 + ANDQ R14, DX + ORQ R10, R8 + XORQ R12, DX + XORQ R13, R8 + MOVQ DX, 176(DI) + MOVQ R8, 184(DI) + + // Revert the internal state to the user state + NOTQ 8(DI) + NOTQ 16(DI) + NOTQ 64(DI) + NOTQ 96(DI) + NOTQ 136(DI) + NOTQ 160(DI) + RET diff --git a/crypto/internal/fips140/sha3/sha3_arm64.go b/crypto/internal/fips140/sha3/sha3_arm64.go new file mode 100644 index 00000000000..dd1e1d3d2f5 --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_arm64.go @@ -0,0 +1,44 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha3 + +import ( + "runtime" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// On non-Apple ARM64, the SHA-3 instructions are apparently slower than the +// pure Go implementation. Checking GOOS is a bit blunt, as it also excludes +// Asahi Linux; we might consider checking the MIDR model in the future. +var useSHA3 = cpu.ARM64HasSHA3 && runtime.GOOS == "darwin" + +func init() { + impl.Register("sha3", "Armv8.2", &useSHA3) +} + +//go:noescape +func keccakF1600NEON(a *[200]byte) + +func keccakF1600(a *[200]byte) { + if useSHA3 { + keccakF1600NEON(a) + } else { + keccakF1600Generic(a) + } +} + +func (d *Digest) write(p []byte) (n int, err error) { + return d.writeGeneric(p) +} +func (d *Digest) read(out []byte) (n int, err error) { + return d.readGeneric(out) +} +func (d *Digest) sum(b []byte) []byte { + return d.sumGeneric(b) +} diff --git a/crypto/internal/fips140/sha3/sha3_arm64.s b/crypto/internal/fips140/sha3/sha3_arm64.s new file mode 100644 index 00000000000..7688d178d51 --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_arm64.s @@ -0,0 +1,165 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func keccakF1600NEON(a *[200]byte) +TEXT ·keccakF1600NEON(SB), $200-8 + MOVD a+0(FP), R0 + MOVD $round_consts<>(SB), R1 + MOVD $24, R2 // counter for loop + + VLD1.P 16(R0), [V0.D1, V1.D1] + VLD1.P 16(R0), [V2.D1, V3.D1] + VLD1.P 16(R0), [V4.D1, V5.D1] + VLD1.P 16(R0), [V6.D1, V7.D1] + VLD1.P 16(R0), [V8.D1, V9.D1] + VLD1.P 16(R0), [V10.D1, V11.D1] + VLD1.P 16(R0), [V12.D1, V13.D1] + VLD1.P 16(R0), [V14.D1, V15.D1] + VLD1.P 16(R0), [V16.D1, V17.D1] + VLD1.P 16(R0), [V18.D1, V19.D1] + VLD1.P 16(R0), [V20.D1, V21.D1] + VLD1.P 16(R0), [V22.D1, V23.D1] + VLD1 (R0), [V24.D1] + + SUB $192, R0, R0 + +loop: + // theta + VEOR3 V20.B16, V15.B16, V10.B16, V25.B16 + VEOR3 V21.B16, V16.B16, V11.B16, V26.B16 + VEOR3 V22.B16, V17.B16, V12.B16, V27.B16 + VEOR3 V23.B16, V18.B16, V13.B16, V28.B16 + VEOR3 V24.B16, V19.B16, V14.B16, V29.B16 + VEOR3 V25.B16, V5.B16, V0.B16, V25.B16 + VEOR3 V26.B16, V6.B16, V1.B16, V26.B16 + VEOR3 V27.B16, V7.B16, V2.B16, V27.B16 + VEOR3 V28.B16, V8.B16, V3.B16, V28.B16 + VEOR3 V29.B16, V9.B16, V4.B16, V29.B16 + + VRAX1 V27.D2, V25.D2, V30.D2 + VRAX1 V28.D2, V26.D2, V31.D2 + VRAX1 V29.D2, V27.D2, V27.D2 + VRAX1 V25.D2, V28.D2, V28.D2 + VRAX1 V26.D2, V29.D2, V29.D2 + + // theta and rho and Pi + VEOR V29.B16, V0.B16, V0.B16 + + VXAR $63, V30.D2, V1.D2, V25.D2 + + VXAR $20, V30.D2, V6.D2, V1.D2 + VXAR $44, V28.D2, V9.D2, V6.D2 + VXAR $3, V31.D2, V22.D2, V9.D2 + VXAR $25, V28.D2, V14.D2, V22.D2 + VXAR $46, V29.D2, V20.D2, V14.D2 + + VXAR $2, V31.D2, V2.D2, V26.D2 + + VXAR $21, V31.D2, V12.D2, V2.D2 + VXAR $39, V27.D2, V13.D2, V12.D2 + VXAR $56, V28.D2, V19.D2, V13.D2 + VXAR $8, V27.D2, V23.D2, V19.D2 + VXAR $23, V29.D2, V15.D2, V23.D2 + + VXAR $37, V28.D2, V4.D2, V15.D2 + + VXAR $50, V28.D2, V24.D2, V28.D2 + VXAR $62, V30.D2, V21.D2, V24.D2 + VXAR $9, V27.D2, V8.D2, V8.D2 + VXAR $19, V30.D2, V16.D2, V4.D2 + VXAR $28, V29.D2, V5.D2, V16.D2 + + VXAR $36, V27.D2, V3.D2, V5.D2 + + VXAR $43, V27.D2, V18.D2, V27.D2 + VXAR $49, V31.D2, V17.D2, V3.D2 + VXAR $54, V30.D2, V11.D2, V30.D2 + VXAR $58, V31.D2, V7.D2, V31.D2 + VXAR $61, V29.D2, V10.D2, V29.D2 + + // chi and iota + VBCAX V8.B16, V22.B16, V26.B16, V20.B16 + VBCAX V22.B16, V23.B16, V8.B16, V21.B16 + VBCAX V23.B16, V24.B16, V22.B16, V22.B16 + VBCAX V24.B16, V26.B16, V23.B16, V23.B16 + VBCAX V26.B16, V8.B16, V24.B16, V24.B16 + + VLD1R.P 8(R1), [V26.D2] + + VBCAX V3.B16, V19.B16, V30.B16, V17.B16 + VBCAX V19.B16, V15.B16, V3.B16, V18.B16 + VBCAX V15.B16, V16.B16, V19.B16, V19.B16 + VBCAX V16.B16, V30.B16, V15.B16, V15.B16 + VBCAX V30.B16, V3.B16, V16.B16, V16.B16 + + VBCAX V31.B16, V12.B16, V25.B16, V10.B16 + VBCAX V12.B16, V13.B16, V31.B16, V11.B16 + VBCAX V13.B16, V14.B16, V12.B16, V12.B16 + VBCAX V14.B16, V25.B16, V13.B16, V13.B16 + VBCAX V25.B16, V31.B16, V14.B16, V14.B16 + + VBCAX V4.B16, V9.B16, V29.B16, V7.B16 + VBCAX V9.B16, V5.B16, V4.B16, V8.B16 + VBCAX V5.B16, V6.B16, V9.B16, V9.B16 + VBCAX V6.B16, V29.B16, V5.B16, V5.B16 + VBCAX V29.B16, V4.B16, V6.B16, V6.B16 + + VBCAX V28.B16, V0.B16, V27.B16, V3.B16 + VBCAX V0.B16, V1.B16, V28.B16, V4.B16 + + VBCAX V1.B16, V2.B16, V0.B16, V0.B16 // iota (chi part) + + VBCAX V2.B16, V27.B16, V1.B16, V1.B16 + VBCAX V27.B16, V28.B16, V2.B16, V2.B16 + + VEOR V26.B16, V0.B16, V0.B16 // iota + + SUB $1, R2, R2 + CBNZ R2, loop + + VST1.P [V0.D1, V1.D1], 16(R0) + VST1.P [V2.D1, V3.D1], 16(R0) + VST1.P [V4.D1, V5.D1], 16(R0) + VST1.P [V6.D1, V7.D1], 16(R0) + VST1.P [V8.D1, V9.D1], 16(R0) + VST1.P [V10.D1, V11.D1], 16(R0) + VST1.P [V12.D1, V13.D1], 16(R0) + VST1.P [V14.D1, V15.D1], 16(R0) + VST1.P [V16.D1, V17.D1], 16(R0) + VST1.P [V18.D1, V19.D1], 16(R0) + VST1.P [V20.D1, V21.D1], 16(R0) + VST1.P [V22.D1, V23.D1], 16(R0) + VST1 [V24.D1], (R0) + + RET + +DATA round_consts<>+0x00(SB)/8, $0x0000000000000001 +DATA round_consts<>+0x08(SB)/8, $0x0000000000008082 +DATA round_consts<>+0x10(SB)/8, $0x800000000000808a +DATA round_consts<>+0x18(SB)/8, $0x8000000080008000 +DATA round_consts<>+0x20(SB)/8, $0x000000000000808b +DATA round_consts<>+0x28(SB)/8, $0x0000000080000001 +DATA round_consts<>+0x30(SB)/8, $0x8000000080008081 +DATA round_consts<>+0x38(SB)/8, $0x8000000000008009 +DATA round_consts<>+0x40(SB)/8, $0x000000000000008a +DATA round_consts<>+0x48(SB)/8, $0x0000000000000088 +DATA round_consts<>+0x50(SB)/8, $0x0000000080008009 +DATA round_consts<>+0x58(SB)/8, $0x000000008000000a +DATA round_consts<>+0x60(SB)/8, $0x000000008000808b +DATA round_consts<>+0x68(SB)/8, $0x800000000000008b +DATA round_consts<>+0x70(SB)/8, $0x8000000000008089 +DATA round_consts<>+0x78(SB)/8, $0x8000000000008003 +DATA round_consts<>+0x80(SB)/8, $0x8000000000008002 +DATA round_consts<>+0x88(SB)/8, $0x8000000000000080 +DATA round_consts<>+0x90(SB)/8, $0x000000000000800a +DATA round_consts<>+0x98(SB)/8, $0x800000008000000a +DATA round_consts<>+0xA0(SB)/8, $0x8000000080008081 +DATA round_consts<>+0xA8(SB)/8, $0x8000000000008080 +DATA round_consts<>+0xB0(SB)/8, $0x0000000080000001 +DATA round_consts<>+0xB8(SB)/8, $0x8000000080008008 +GLOBL round_consts<>(SB), NOPTR|RODATA, $192 diff --git a/crypto/internal/fips140/sha3/sha3_noasm.go b/crypto/internal/fips140/sha3/sha3_noasm.go new file mode 100644 index 00000000000..1ce3edfb6fe --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_noasm.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !arm64 && !s390x) || purego + +package sha3 + +func keccakF1600(a *[200]byte) { + keccakF1600Generic(a) +} + +func (d *Digest) write(p []byte) (n int, err error) { + return d.writeGeneric(p) +} +func (d *Digest) read(out []byte) (n int, err error) { + return d.readGeneric(out) +} +func (d *Digest) sum(b []byte) []byte { + return d.sumGeneric(b) +} diff --git a/crypto/internal/fips140/sha3/sha3_s390x.go b/crypto/internal/fips140/sha3/sha3_s390x.go new file mode 100644 index 00000000000..fa4e8c4ceac --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_s390x.go @@ -0,0 +1,196 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha3 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// This file contains code for using the 'compute intermediate +// message digest' (KIMD) and 'compute last message digest' (KLMD) +// instructions to compute SHA-3 and SHAKE hashes on IBM Z. See +// [z/Architecture Principles of Operation, Fourteen Edition]. +// +// [z/Architecture Principles of Operation, Fourteen Edition]: https://www.ibm.com/docs/en/module_1678991624569/pdf/SA22-7832-13.pdf + +var useSHA3 = cpu.S390XHasSHA3 + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + impl.Register("sha3", "CPACF", &useSHA3) +} + +func keccakF1600(a *[200]byte) { + keccakF1600Generic(a) +} + +// codes represent 7-bit KIMD/KLMD function codes as defined in +// the Principles of Operation. +type code uint64 + +const ( + // Function codes for KIMD/KLMD, from Figure 7-207. + sha3_224 code = 32 + sha3_256 code = 33 + sha3_384 code = 34 + sha3_512 code = 35 + shake_128 code = 36 + shake_256 code = 37 + nopad = 0x100 +) + +// kimd is a wrapper for the 'compute intermediate message digest' instruction. +// src is absorbed into the sponge state a. +// len(src) must be a multiple of the rate for the given function code. +// +//go:noescape +func kimd(function code, a *[200]byte, src []byte) + +// klmd is a wrapper for the 'compute last message digest' instruction. +// src is padded and absorbed into the sponge state a. +// +// If the function is a SHAKE XOF, the sponge is then optionally squeezed into +// dst by first applying the permutation and then copying the output until dst +// runs out. If len(dst) is a multiple of rate (including zero), the final +// permutation is not applied. If the nopad bit of function is set and len(src) +// is zero, only squeezing is performed. +// +//go:noescape +func klmd(function code, a *[200]byte, dst, src []byte) + +func (d *Digest) write(p []byte) (n int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: Write after Read") + } + if !useSHA3 { + return d.writeGeneric(p) + } + + n = len(p) + + // If there is buffered input in the state, keep XOR'ing. + if d.n > 0 { + x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) + d.n += x + p = p[x:] + } + + // If the sponge is full, apply the permutation. + if d.n == d.rate { + // Absorbing a "rate"ful of zeroes effectively XORs the state with + // zeroes (a no-op) and then runs the permutation. The actual function + // doesn't matter, they all run the same permutation. + kimd(shake_128, &d.a, make([]byte, rateK256)) + d.n = 0 + } + + // Absorb full blocks with KIMD. + if len(p) >= d.rate { + wholeBlocks := len(p) / d.rate * d.rate + kimd(d.function(), &d.a, p[:wholeBlocks]) + p = p[wholeBlocks:] + } + + // If there is any trailing input, XOR it into the state. + if len(p) > 0 { + d.n += subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) + } + + return +} + +func (d *Digest) sum(b []byte) []byte { + if d.state != spongeAbsorbing { + panic("sha3: Sum after Read") + } + if !useSHA3 || d.dsbyte != dsbyteSHA3 && d.dsbyte != dsbyteShake { + return d.sumGeneric(b) + } + + // Copy the state to preserve the original. + a := d.a + + // We "absorb" a buffer of zeroes as long as the amount of input we already + // XOR'd into the sponge, to skip over it. The max cap is specified to avoid + // an allocation. + buf := make([]byte, d.n, rateK256) + function := d.function() + switch function { + case sha3_224, sha3_256, sha3_384, sha3_512: + klmd(function, &a, nil, buf) + return append(b, a[:d.outputLen]...) + case shake_128, shake_256: + h := make([]byte, d.outputLen, 64) + klmd(function, &a, h, buf) + return append(b, h...) + default: + panic("sha3: unknown function") + } +} + +func (d *Digest) read(out []byte) (n int, err error) { + if !useSHA3 || d.dsbyte != dsbyteShake { + return d.readGeneric(out) + } + + n = len(out) + + if d.state == spongeAbsorbing { + d.state = spongeSqueezing + + // We "absorb" a buffer of zeroes as long as the amount of input we + // already XOR'd into the sponge, to skip over it. The max cap is + // specified to avoid an allocation. + buf := make([]byte, d.n, rateK256) + klmd(d.function(), &d.a, out, buf) + } else { + // We have "buffered" output still to copy. + if d.n < d.rate { + x := copy(out, d.a[d.n:d.rate]) + d.n += x + out = out[x:] + } + if len(out) == 0 { + return + } + + klmd(d.function()|nopad, &d.a, out, nil) + } + + if len(out)%d.rate == 0 { + // The final permutation was not performed, + // so there is no "buffered" output. + d.n = d.rate + } else { + d.n = len(out) % d.rate + } + + return +} + +func (d *Digest) function() code { + switch d.rate { + case rateK256: + return shake_128 + case rateK448: + return sha3_224 + case rateK512: + if d.dsbyte == dsbyteSHA3 { + return sha3_256 + } else { + return shake_256 + } + case rateK768: + return sha3_384 + case rateK1024: + return sha3_512 + default: + panic("invalid rate") + } +} diff --git a/crypto/internal/fips140/sha3/sha3_s390x.s b/crypto/internal/fips140/sha3/sha3_s390x.s new file mode 100644 index 00000000000..0ce277160e7 --- /dev/null +++ b/crypto/internal/fips140/sha3/sha3_s390x.s @@ -0,0 +1,32 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func kimd(function code, a *[200]byte, src []byte) +TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 + MOVD function+0(FP), R0 + MOVD a+8(FP), R1 + LMG src+16(FP), R2, R3 // R2=base, R3=len + +continue: + KIMD R0, R2 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET + +// func klmd(function code, a *[200]byte, dst, src []byte) +TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 + MOVD function+0(FP), R0 + MOVD a+8(FP), R1 + LMG dst+16(FP), R2, R3 // R2=base, R3=len + LMG src+40(FP), R4, R5 // R4=base, R5=len + +continue: + KLMD R2, R4 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET diff --git a/crypto/internal/fips140/sha3/shake.go b/crypto/internal/fips140/sha3/shake.go new file mode 100644 index 00000000000..91e19d07230 --- /dev/null +++ b/crypto/internal/fips140/sha3/shake.go @@ -0,0 +1,152 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +import ( + "bytes" + "errors" + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +type SHAKE struct { + d Digest // SHA-3 state context and Read/Write operations + + // initBlock is the cSHAKE specific initialization set of bytes. It is initialized + // by newCShake function and stores concatenation of N followed by S, encoded + // by the method specified in 3.3 of [1]. + // It is stored here in order for Reset() to be able to put context into + // initial state. + initBlock []byte +} + +func bytepad(data []byte, rate int) []byte { + out := make([]byte, 0, 9+len(data)+rate-1) + out = append(out, leftEncode(uint64(rate))...) + out = append(out, data...) + if padlen := rate - len(out)%rate; padlen < rate { + out = append(out, make([]byte, padlen)...) + } + return out +} + +func leftEncode(x uint64) []byte { + // Let n be the smallest positive integer for which 2^(8n) > x. + n := (bits.Len64(x) + 7) / 8 + if n == 0 { + n = 1 + } + // Return n || x with n as a byte and x an n bytes in big-endian order. + b := make([]byte, 9) + byteorder.BEPutUint64(b[1:], x) + b = b[9-n-1:] + b[0] = byte(n) + return b +} + +func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) *SHAKE { + c := &SHAKE{d: Digest{rate: rate, outputLen: outputLen, dsbyte: dsbyte}} + c.initBlock = make([]byte, 0, 9+len(N)+9+len(S)) // leftEncode returns max 9 bytes + c.initBlock = append(c.initBlock, leftEncode(uint64(len(N))*8)...) + c.initBlock = append(c.initBlock, N...) + c.initBlock = append(c.initBlock, leftEncode(uint64(len(S))*8)...) + c.initBlock = append(c.initBlock, S...) + c.Write(bytepad(c.initBlock, c.d.rate)) + return c +} + +func (s *SHAKE) BlockSize() int { return s.d.BlockSize() } +func (s *SHAKE) Size() int { return s.d.Size() } + +// Sum appends a portion of output to b and returns the resulting slice. The +// output length is selected to provide full-strength generic security: 32 bytes +// for SHAKE128 and 64 bytes for SHAKE256. It does not change the underlying +// state. It panics if any output has already been read. +func (s *SHAKE) Sum(in []byte) []byte { return s.d.Sum(in) } + +// Write absorbs more data into the hash's state. +// It panics if any output has already been read. +func (s *SHAKE) Write(p []byte) (n int, err error) { return s.d.Write(p) } + +func (s *SHAKE) Read(out []byte) (n int, err error) { + fips140.RecordApproved() + // Note that read is not exposed on Digest since SHA-3 does not offer + // variable output length. It is only used internally by Sum. + return s.d.read(out) +} + +// Reset resets the hash to initial state. +func (s *SHAKE) Reset() { + s.d.Reset() + if len(s.initBlock) != 0 { + s.Write(bytepad(s.initBlock, s.d.rate)) + } +} + +// Clone returns a copy of the SHAKE context in its current state. +func (s *SHAKE) Clone() *SHAKE { + ret := *s + return &ret +} + +func (s *SHAKE) MarshalBinary() ([]byte, error) { + return s.AppendBinary(make([]byte, 0, marshaledSize+len(s.initBlock))) +} + +func (s *SHAKE) AppendBinary(b []byte) ([]byte, error) { + b, err := s.d.AppendBinary(b) + if err != nil { + return nil, err + } + b = append(b, s.initBlock...) + return b, nil +} + +func (s *SHAKE) UnmarshalBinary(b []byte) error { + if len(b) < marshaledSize { + return errors.New("sha3: invalid hash state") + } + if err := s.d.UnmarshalBinary(b[:marshaledSize]); err != nil { + return err + } + s.initBlock = bytes.Clone(b[marshaledSize:]) + return nil +} + +// NewShake128 creates a new SHAKE128 XOF. +func NewShake128() *SHAKE { + return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}} +} + +// NewShake256 creates a new SHAKE256 XOF. +func NewShake256() *SHAKE { + return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}} +} + +// NewCShake128 creates a new cSHAKE128 XOF. +// +// N is used to define functions based on cSHAKE, it can be empty when plain +// cSHAKE is desired. S is a customization byte string used for domain +// separation. When N and S are both empty, this is equivalent to NewShake128. +func NewCShake128(N, S []byte) *SHAKE { + if len(N) == 0 && len(S) == 0 { + return NewShake128() + } + return newCShake(N, S, rateK256, 32, dsbyteCShake) +} + +// NewCShake256 creates a new cSHAKE256 XOF. +// +// N is used to define functions based on cSHAKE, it can be empty when plain +// cSHAKE is desired. S is a customization byte string used for domain +// separation. When N and S are both empty, this is equivalent to NewShake256. +func NewCShake256(N, S []byte) *SHAKE { + if len(N) == 0 && len(S) == 0 { + return NewShake256() + } + return newCShake(N, S, rateK512, 64, dsbyteCShake) +} diff --git a/crypto/internal/fips140/sha512/_asm/go.mod b/crypto/internal/fips140/sha512/_asm/go.mod new file mode 100644 index 00000000000..78b953258b6 --- /dev/null +++ b/crypto/internal/fips140/sha512/_asm/go.mod @@ -0,0 +1,11 @@ +module crypto/sha512/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/internal/fips140/sha512/_asm/go.sum b/crypto/internal/fips140/sha512/_asm/go.sum new file mode 100644 index 00000000000..76af484b2eb --- /dev/null +++ b/crypto/internal/fips140/sha512/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/sha512/_asm/sha512block_amd64_asm.go b/crypto/internal/fips140/sha512/_asm/sha512block_amd64_asm.go similarity index 82% rename from crypto/sha512/_asm/sha512block_amd64_asm.go rename to crypto/internal/fips140/sha512/_asm/sha512block_amd64_asm.go index f8f8b737b07..e62aae9781d 100644 --- a/crypto/sha512/_asm/sha512block_amd64_asm.go +++ b/crypto/internal/fips140/sha512/_asm/sha512block_amd64_asm.go @@ -5,12 +5,14 @@ package main import ( + "os" + . "github.com/mmcloughlin/avo/build" . "github.com/mmcloughlin/avo/operand" . "github.com/mmcloughlin/avo/reg" ) -//go:generate go run . -out ../sha512block_amd64.s -pkg sha512 +//go:generate go run . -out ../sha512block_amd64.s // SHA512 block routine. See sha512block.go for Go equivalent. // @@ -138,219 +140,16 @@ var _K = []uint64{ } func main() { - Package("github.com/runZeroInc/excrypto/crypto/sha512") + // https://github.com/mmcloughlin/avo/issues/450 + os.Setenv("GOOS", "linux") + os.Setenv("GOARCH", "amd64") + + Package("github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512") ConstraintExpr("!purego") - blockAMD64() blockAVX2() Generate() } -// Wt = Mt; for 0 <= t <= 15 -// -// Line 50 -func MSGSCHEDULE0(index int) { - MOVQ(Mem{Base: SI}.Offset(index*8), RAX) - BSWAPQ(RAX) - MOVQ(RAX, Mem{Base: BP}.Offset(index*8)) -} - -// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 79 -// -// SIGMA0(x) = ROTR(1,x) XOR ROTR(8,x) XOR SHR(7,x) -// SIGMA1(x) = ROTR(19,x) XOR ROTR(61,x) XOR SHR(6,x) -// -// Line 58 -func MSGSCHEDULE1(index int) { - MOVQ(Mem{Base: BP}.Offset((index-2)*8), RAX) - MOVQ(RAX, RCX) - RORQ(Imm(19), RAX) - MOVQ(RCX, RDX) - RORQ(Imm(61), RCX) - SHRQ(Imm(6), RDX) - MOVQ(Mem{Base: BP}.Offset((index-15)*8), RBX) - XORQ(RCX, RAX) - MOVQ(RBX, RCX) - XORQ(RDX, RAX) - RORQ(Imm(1), RBX) - MOVQ(RCX, RDX) - SHRQ(Imm(7), RDX) - RORQ(Imm(8), RCX) - ADDQ(Mem{Base: BP}.Offset((index-7)*8), RAX) - XORQ(RCX, RBX) - XORQ(RDX, RBX) - ADDQ(Mem{Base: BP}.Offset((index-16)*8), RBX) - ADDQ(RBX, RAX) - MOVQ(RAX, Mem{Base: BP}.Offset((index)*8)) -} - -// Calculate T1 in AX - uses AX, CX and DX registers. -// h is also used as an accumulator. Wt is passed in AX. -// -// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt -// BIGSIGMA1(x) = ROTR(14,x) XOR ROTR(18,x) XOR ROTR(41,x) -// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) -// -// Line 85 -func SHA512T1(konst uint64, e, f, g, h GPPhysical) { - MOVQ(U64(konst), RDX) - ADDQ(RAX, h) - MOVQ(e, RAX) - ADDQ(RDX, h) - MOVQ(e, RCX) - RORQ(U8(14), RAX) - MOVQ(e, RDX) - RORQ(U8(18), RCX) - XORQ(RCX, RAX) - MOVQ(e, RCX) - RORQ(U8(41), RDX) - ANDQ(f, RCX) - XORQ(RAX, RDX) - MOVQ(e, RAX) - NOTQ(RAX) - ADDQ(RDX, h) - ANDQ(g, RAX) - XORQ(RCX, RAX) - ADDQ(h, RAX) -} - -// Calculate T2 in BX - uses BX, CX, DX and DI registers. -// -// T2 = BIGSIGMA0(a) + Maj(a, b, c) -// BIGSIGMA0(x) = ROTR(28,x) XOR ROTR(34,x) XOR ROTR(39,x) -// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) -// -// Line 110 -func SHA512T2(a, b, c GPPhysical) { - MOVQ(a, RDI) - MOVQ(c, RBX) - RORQ(Imm(28), RDI) - MOVQ(a, RDX) - ANDQ(b, RBX) - RORQ(Imm(34), RDX) - MOVQ(a, RCX) - ANDQ(c, RCX) - XORQ(RDX, RDI) - XORQ(RCX, RBX) - MOVQ(a, RDX) - MOVQ(b, RCX) - RORQ(Imm(39), RDX) - ANDQ(a, RCX) - XORQ(RCX, RBX) - XORQ(RDX, RDI) - ADDQ(RDI, RBX) -} - -// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. -// The values for e and a are stored in d and h, ready for rotation. -// -// Line 131 -func SHA512ROUND(index int, konst uint64, a, b, c, d, e, f, g, h GPPhysical) { - SHA512T1(konst, e, f, g, h) - SHA512T2(a, b, c) - MOVQ(RBX, h) - ADDQ(RAX, d) - ADDQ(RAX, h) -} - -// Line 169 -func SHA512ROUND0(index int, konst uint64, a, b, c, d, e, f, g, h GPPhysical) { - MSGSCHEDULE0(index) - SHA512ROUND(index, konst, a, b, c, d, e, f, g, h) -} - -// Line 142 -func SHA512ROUND1(index int, konst uint64, a, b, c, d, e, f, g, h GPPhysical) { - MSGSCHEDULE1(index) - SHA512ROUND(index, konst, a, b, c, d, e, f, g, h) -} - -// Line 146 -func blockAMD64() { - Implement("blockAMD64") - AllocLocal(648) - - Load(Param("p").Base(), RSI) - Load(Param("p").Len(), RDX) - SHRQ(Imm(7), RDX) - SHLQ(Imm(7), RDX) - - LEAQ(Mem{Base: SI, Index: DX, Scale: 1}, RDI) - MOVQ(RDI, Mem{Base: SP}.Offset(640)) - CMPQ(RSI, RDI) - JEQ(LabelRef("end")) - - Load(Param("dig"), RBP) - MOVQ(Mem{Base: BP}.Offset(0*8), R8) // a = H0 - MOVQ(Mem{Base: BP}.Offset(1*8), R9) // b = H1 - MOVQ(Mem{Base: BP}.Offset(2*8), R10) // c = H2 - MOVQ(Mem{Base: BP}.Offset(3*8), R11) // d = H3 - MOVQ(Mem{Base: BP}.Offset(4*8), R12) // e = H4 - MOVQ(Mem{Base: BP}.Offset(5*8), R13) // f = H5 - MOVQ(Mem{Base: BP}.Offset(6*8), R14) // g = H6 - MOVQ(Mem{Base: BP}.Offset(7*8), R15) // h = H7 - PSHUFFLE_BYTE_FLIP_MASK_DATA() - loop() - end() -} - -func rotateRight(slice *[]GPPhysical) []GPPhysical { - n := len(*slice) - new := make([]GPPhysical, n) - for i, reg := range *slice { - new[(i+1)%n] = reg - } - return new -} - -// Line 167 -func loop() { - Label("loop") - MOVQ(RSP, RBP) // message schedule - - n := len(_K) - regs := []GPPhysical{R8, R9, R10, R11, R12, R13, R14, R15} - - for i := 0; i < 16; i++ { - SHA512ROUND0(i, _K[i], regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]) - regs = rotateRight(®s) - } - - for i := 16; i < n; i++ { - SHA512ROUND1(i, _K[i], regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]) - regs = rotateRight(®s) - } - - Load(Param("dig"), RBP) - - BP_Mem := Mem{Base: BP} - ADDQ(BP_Mem.Offset(0*8), R8) // H0 = a + H0 - MOVQ(R8, BP_Mem.Offset(0*8)) - ADDQ(BP_Mem.Offset(1*8), R9) // H1 = b + H1 - MOVQ(R9, BP_Mem.Offset(1*8)) - ADDQ(BP_Mem.Offset(2*8), R10) // H2 = c + H2 - MOVQ(R10, BP_Mem.Offset(2*8)) - ADDQ(BP_Mem.Offset(3*8), R11) // H3 = d + H3 - MOVQ(R11, BP_Mem.Offset(3*8)) - ADDQ(BP_Mem.Offset(4*8), R12) // H4 = e + H4 - MOVQ(R12, BP_Mem.Offset(4*8)) - ADDQ(BP_Mem.Offset(5*8), R13) // H5 = f + H5 - MOVQ(R13, BP_Mem.Offset(5*8)) - ADDQ(BP_Mem.Offset(6*8), R14) // H6 = g + H6 - MOVQ(R14, BP_Mem.Offset(6*8)) - ADDQ(BP_Mem.Offset(7*8), R15) // H7 = h + H7 - MOVQ(R15, BP_Mem.Offset(7*8)) - - ADDQ(Imm(128), RSI) - CMPQ(RSI, Mem{Base: SP}.Offset(640)) - JB(LabelRef("loop")) -} - -// Line 274 -func end() { - Label("end") - RET() -} - // Version below is based on "Fast SHA512 Implementations on Intel // Architecture Processors" White-paper // https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-sha512-implementations-ia-processors-paper.pdf @@ -432,7 +231,7 @@ func blockAVX2() { func loop0() { Label("loop0") - _K := NewDataAddr(Symbol{Name: ThatPeskyUnicodeDot + "_K"}, 0) + _K := NewDataAddr(Symbol{Name: "$" + ThatPeskyUnicodeDot + "_K"}, 0) MOVQ(_K, RBP) // byte swap first 16 dwords diff --git a/crypto/internal/fips140/sha512/cast.go b/crypto/internal/fips140/sha512/cast.go new file mode 100644 index 00000000000..b8c9fdf8b82 --- /dev/null +++ b/crypto/internal/fips140/sha512/cast.go @@ -0,0 +1,37 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha512 + +import ( + "bytes" + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" +) + +func init() { + fips140.CAST("SHA2-512", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0xb4, 0xc4, 0xe0, 0x46, 0x82, 0x6b, 0xd2, 0x61, + 0x90, 0xd0, 0x97, 0x15, 0xfc, 0x31, 0xf4, 0xe6, + 0xa7, 0x28, 0x20, 0x4e, 0xad, 0xd1, 0x12, 0x90, + 0x5b, 0x08, 0xb1, 0x4b, 0x7f, 0x15, 0xc4, 0xf3, + 0x8e, 0x29, 0xb2, 0xfc, 0x54, 0x26, 0x5a, 0x12, + 0x63, 0x26, 0xc5, 0xbd, 0xea, 0x66, 0xc1, 0xb0, + 0x8e, 0x9e, 0x47, 0x72, 0x3b, 0x2d, 0x70, 0x06, + 0x5a, 0xc1, 0x26, 0x2e, 0xcc, 0x37, 0xbf, 0xb1, + } + h := New() + h.Write(input) + if got := h.Sum(nil); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/sha512/sha512.go b/crypto/internal/fips140/sha512/sha512.go new file mode 100644 index 00000000000..5db1c702899 --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512.go @@ -0,0 +1,308 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 +// hash algorithms as defined in FIPS 180-4. +package sha512 + +import ( + "errors" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/hash" +) + +const ( + // size512 is the size, in bytes, of a SHA-512 checksum. + size512 = 64 + + // size224 is the size, in bytes, of a SHA-512/224 checksum. + size224 = 28 + + // size256 is the size, in bytes, of a SHA-512/256 checksum. + size256 = 32 + + // size384 is the size, in bytes, of a SHA-384 checksum. + size384 = 48 + + // blockSize is the block size, in bytes, of the SHA-512/224, + // SHA-512/256, SHA-384 and SHA-512 hash functions. + blockSize = 128 +) + +const ( + chunk = 128 + init0 = 0x6a09e667f3bcc908 + init1 = 0xbb67ae8584caa73b + init2 = 0x3c6ef372fe94f82b + init3 = 0xa54ff53a5f1d36f1 + init4 = 0x510e527fade682d1 + init5 = 0x9b05688c2b3e6c1f + init6 = 0x1f83d9abfb41bd6b + init7 = 0x5be0cd19137e2179 + init0_224 = 0x8c3d37c819544da2 + init1_224 = 0x73e1996689dcd4d6 + init2_224 = 0x1dfab7ae32ff9c82 + init3_224 = 0x679dd514582f9fcf + init4_224 = 0x0f6d2b697bd44da8 + init5_224 = 0x77e36f7304c48942 + init6_224 = 0x3f9d85a86a1d36c8 + init7_224 = 0x1112e6ad91d692a1 + init0_256 = 0x22312194fc2bf72c + init1_256 = 0x9f555fa3c84c64c2 + init2_256 = 0x2393b86b6f53b151 + init3_256 = 0x963877195940eabd + init4_256 = 0x96283ee2a88effe3 + init5_256 = 0xbe5e1e2553863992 + init6_256 = 0x2b0199fc2c85b8aa + init7_256 = 0x0eb72ddc81c52ca2 + init0_384 = 0xcbbb9d5dc1059ed8 + init1_384 = 0x629a292a367cd507 + init2_384 = 0x9159015a3070dd17 + init3_384 = 0x152fecd8f70e5939 + init4_384 = 0x67332667ffc00b31 + init5_384 = 0x8eb44a8768581511 + init6_384 = 0xdb0c2e0d64f98fa7 + init7_384 = 0x47b5481dbefa4fa4 +) + +// Digest is a SHA-384, SHA-512, SHA-512/224, or SHA-512/256 [hash.Hash] +// implementation. +type Digest struct { + h [8]uint64 + x [chunk]byte + nx int + len uint64 + size int // size224, size256, size384, or size512 +} + +func (d *Digest) Reset() { + switch d.size { + case size384: + d.h[0] = init0_384 + d.h[1] = init1_384 + d.h[2] = init2_384 + d.h[3] = init3_384 + d.h[4] = init4_384 + d.h[5] = init5_384 + d.h[6] = init6_384 + d.h[7] = init7_384 + case size224: + d.h[0] = init0_224 + d.h[1] = init1_224 + d.h[2] = init2_224 + d.h[3] = init3_224 + d.h[4] = init4_224 + d.h[5] = init5_224 + d.h[6] = init6_224 + d.h[7] = init7_224 + case size256: + d.h[0] = init0_256 + d.h[1] = init1_256 + d.h[2] = init2_256 + d.h[3] = init3_256 + d.h[4] = init4_256 + d.h[5] = init5_256 + d.h[6] = init6_256 + d.h[7] = init7_256 + case size512: + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.h[5] = init5 + d.h[6] = init6 + d.h[7] = init7 + default: + panic("unknown size") + } + d.nx = 0 + d.len = 0 +} + +const ( + magic384 = "sha\x04" + magic512_224 = "sha\x05" + magic512_256 = "sha\x06" + magic512 = "sha\x07" + marshaledSize = len(magic512) + 8*8 + chunk + 8 +) + +func (d *Digest) MarshalBinary() ([]byte, error) { + return d.AppendBinary(make([]byte, 0, marshaledSize)) +} + +func (d *Digest) AppendBinary(b []byte) ([]byte, error) { + switch d.size { + case size384: + b = append(b, magic384...) + case size224: + b = append(b, magic512_224...) + case size256: + b = append(b, magic512_256...) + case size512: + b = append(b, magic512...) + default: + panic("unknown size") + } + b = byteorder.BEAppendUint64(b, d.h[0]) + b = byteorder.BEAppendUint64(b, d.h[1]) + b = byteorder.BEAppendUint64(b, d.h[2]) + b = byteorder.BEAppendUint64(b, d.h[3]) + b = byteorder.BEAppendUint64(b, d.h[4]) + b = byteorder.BEAppendUint64(b, d.h[5]) + b = byteorder.BEAppendUint64(b, d.h[6]) + b = byteorder.BEAppendUint64(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = append(b, make([]byte, len(d.x)-d.nx)...) + b = byteorder.BEAppendUint64(b, d.len) + return b, nil +} + +func (d *Digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic512) { + return errors.New("crypto/sha512: invalid hash state identifier") + } + switch { + case d.size == size384 && string(b[:len(magic384)]) == magic384: + case d.size == size224 && string(b[:len(magic512_224)]) == magic512_224: + case d.size == size256 && string(b[:len(magic512_256)]) == magic512_256: + case d.size == size512 && string(b[:len(magic512)]) == magic512: + default: + return errors.New("crypto/sha512: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/sha512: invalid hash state size") + } + b = b[len(magic512):] + b, d.h[0] = consumeUint64(b) + b, d.h[1] = consumeUint64(b) + b, d.h[2] = consumeUint64(b) + b, d.h[3] = consumeUint64(b) + b, d.h[4] = consumeUint64(b) + b, d.h[5] = consumeUint64(b) + b, d.h[6] = consumeUint64(b) + b, d.h[7] = consumeUint64(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % chunk) + return nil +} + +func consumeUint64(b []byte) ([]byte, uint64) { + return b[8:], byteorder.BEUint64(b) +} + +func (d *Digest) Clone() (hash.Cloner, error) { + r := *d + return &r, nil +} + +// New returns a new Digest computing the SHA-512 hash. +func New() *Digest { + d := &Digest{size: size512} + d.Reset() + return d +} + +// New512_224 returns a new Digest computing the SHA-512/224 hash. +func New512_224() *Digest { + d := &Digest{size: size224} + d.Reset() + return d +} + +// New512_256 returns a new Digest computing the SHA-512/256 hash. +func New512_256() *Digest { + d := &Digest{size: size256} + d.Reset() + return d +} + +// New384 returns a new Digest computing the SHA-384 hash. +func New384() *Digest { + d := &Digest{size: size384} + d.Reset() + return d +} + +func (d *Digest) Size() int { + return d.size +} + +func (d *Digest) BlockSize() int { return blockSize } + +func (d *Digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *Digest) Sum(in []byte) []byte { + fips140.RecordApproved() + // Make a copy of d so that caller can keep writing and summing. + d0 := new(Digest) + *d0 = *d + hash := d0.checkSum() + return append(in, hash[:d.size]...) +} + +func (d *Digest) checkSum() [size512]byte { + // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. + len := d.len + var tmp [128 + 16]byte // padding + length buffer + tmp[0] = 0x80 + var t uint64 + if len%128 < 112 { + t = 112 - len%128 + } else { + t = 128 + 112 - len%128 + } + + // Length in bits. + len <<= 3 + padlen := tmp[:t+16] + // Upper 64 bits are always zero, because len variable has type uint64, + // and tmp is already zeroed at that index, so we can skip updating it. + // byteorder.BEPutUint64(padlen[t+0:], 0) + byteorder.BEPutUint64(padlen[t+8:], len) + d.Write(padlen) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [size512]byte + byteorder.BEPutUint64(digest[0:], d.h[0]) + byteorder.BEPutUint64(digest[8:], d.h[1]) + byteorder.BEPutUint64(digest[16:], d.h[2]) + byteorder.BEPutUint64(digest[24:], d.h[3]) + byteorder.BEPutUint64(digest[32:], d.h[4]) + byteorder.BEPutUint64(digest[40:], d.h[5]) + if d.size != size384 { + byteorder.BEPutUint64(digest[48:], d.h[6]) + byteorder.BEPutUint64(digest[56:], d.h[7]) + } + + return digest +} diff --git a/crypto/sha512/sha512block.go b/crypto/internal/fips140/sha512/sha512block.go similarity index 98% rename from crypto/sha512/sha512block.go rename to crypto/internal/fips140/sha512/sha512block.go index 81569c5f84e..517e8389f7e 100644 --- a/crypto/sha512/sha512block.go +++ b/crypto/internal/fips140/sha512/sha512block.go @@ -10,7 +10,7 @@ package sha512 import "math/bits" -var _K = []uint64{ +var _K = [...]uint64{ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, @@ -93,7 +93,7 @@ var _K = []uint64{ 0x6c44198c4a475817, } -func blockGeneric(dig *digest, p []byte) { +func blockGeneric(dig *Digest, p []byte) { var w [80]uint64 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] for len(p) >= chunk { diff --git a/crypto/internal/fips140/sha512/sha512block_amd64.go b/crypto/internal/fips140/sha512/sha512block_amd64.go new file mode 100644 index 00000000000..4c8c2cb64a3 --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512block_amd64.go @@ -0,0 +1,29 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha512 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useAVX2 = cpu.X86HasAVX && cpu.X86HasAVX2 && cpu.X86HasBMI2 + +func init() { + impl.Register("sha512", "AVX2", &useAVX2) +} + +//go:noescape +func blockAVX2(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useAVX2 { + blockAVX2(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/internal/fips140/sha512/sha512block_amd64.s b/crypto/internal/fips140/sha512/sha512block_amd64.s new file mode 100644 index 00000000000..e11d509ab4b --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512block_amd64.s @@ -0,0 +1,904 @@ +// Code generated by command: go run sha512block_amd64_asm.go -out ../sha512block_amd64.s. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +// func blockAVX2(dig *Digest, p []byte) +// Requires: AVX, AVX2, BMI2 +TEXT ·blockAVX2(SB), NOSPLIT, $56-32 + MOVQ dig+0(FP), SI + MOVQ p_base+8(FP), DI + MOVQ p_len+16(FP), DX + SHRQ $0x07, DX + SHLQ $0x07, DX + JZ done_hash + ADDQ DI, DX + MOVQ DX, 48(SP) + MOVQ (SI), AX + MOVQ 8(SI), BX + MOVQ 16(SI), CX + MOVQ 24(SI), R8 + MOVQ 32(SI), DX + MOVQ 40(SI), R9 + MOVQ 48(SI), R10 + MOVQ 56(SI), R11 + VMOVDQU PSHUFFLE_BYTE_FLIP_MASK<>+0(SB), Y9 + +loop0: + MOVQ $·_K+0(SB), BP + VMOVDQU (DI), Y4 + VPSHUFB Y9, Y4, Y4 + VMOVDQU 32(DI), Y5 + VPSHUFB Y9, Y5, Y5 + VMOVDQU 64(DI), Y6 + VPSHUFB Y9, Y6, Y6 + VMOVDQU 96(DI), Y7 + VPSHUFB Y9, Y7, Y7 + MOVQ DI, 40(SP) + MOVQ $0x00000004, 32(SP) + +loop1: + VPADDQ (BP), Y4, Y0 + VMOVDQU Y0, (SP) + VPERM2F128 $0x03, Y6, Y7, Y0 + VPALIGNR $0x08, Y6, Y0, Y0 + VPADDQ Y4, Y0, Y0 + VPERM2F128 $0x03, Y4, Y5, Y1 + VPALIGNR $0x08, Y4, Y1, Y1 + VPSRLQ $0x01, Y1, Y2 + VPSLLQ $0x3f, Y1, Y3 + VPOR Y2, Y3, Y3 + VPSRLQ $0x07, Y1, Y8 + MOVQ AX, DI + RORXQ $0x29, DX, R13 + RORXQ $0x12, DX, R14 + ADDQ (SP), R11 + ORQ CX, DI + MOVQ R9, R15 + RORXQ $0x22, AX, R12 + XORQ R14, R13 + XORQ R10, R15 + RORXQ $0x0e, DX, R14 + ANDQ DX, R15 + XORQ R14, R13 + RORXQ $0x27, AX, R14 + ADDQ R11, R8 + ANDQ BX, DI + XORQ R12, R14 + RORXQ $0x1c, AX, R12 + XORQ R10, R15 + XORQ R12, R14 + MOVQ AX, R12 + ANDQ CX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R11 + ADDQ R15, R8 + ADDQ R15, R11 + ADDQ DI, R11 + VPSRLQ $0x08, Y1, Y2 + VPSLLQ $0x38, Y1, Y1 + VPOR Y2, Y1, Y1 + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + VPADDQ Y1, Y0, Y0 + VPERM2F128 $0x00, Y0, Y0, Y4 + VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 + VPERM2F128 $0x11, Y7, Y7, Y2 + VPSRLQ $0x06, Y2, Y8 + MOVQ R11, DI + RORXQ $0x29, R8, R13 + RORXQ $0x12, R8, R14 + ADDQ 8(SP), R10 + ORQ BX, DI + MOVQ DX, R15 + RORXQ $0x22, R11, R12 + XORQ R14, R13 + XORQ R9, R15 + RORXQ $0x0e, R8, R14 + XORQ R14, R13 + RORXQ $0x27, R11, R14 + ANDQ R8, R15 + ADDQ R10, CX + ANDQ AX, DI + XORQ R12, R14 + RORXQ $0x1c, R11, R12 + XORQ R9, R15 + XORQ R12, R14 + MOVQ R11, R12 + ANDQ BX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R10 + ADDQ R15, CX + ADDQ R15, R10 + ADDQ DI, R10 + VPSRLQ $0x13, Y2, Y3 + VPSLLQ $0x2d, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y2, Y3 + VPSLLQ $0x03, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y4, Y4 + VPSRLQ $0x06, Y4, Y8 + MOVQ R10, DI + RORXQ $0x29, CX, R13 + ADDQ 16(SP), R9 + RORXQ $0x12, CX, R14 + ORQ AX, DI + MOVQ R8, R15 + XORQ DX, R15 + RORXQ $0x22, R10, R12 + XORQ R14, R13 + ANDQ CX, R15 + RORXQ $0x0e, CX, R14 + ADDQ R9, BX + ANDQ R11, DI + XORQ R14, R13 + RORXQ $0x27, R10, R14 + XORQ DX, R15 + XORQ R12, R14 + RORXQ $0x1c, R10, R12 + XORQ R12, R14 + MOVQ R10, R12 + ANDQ AX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R9 + ADDQ R15, BX + ADDQ R15, R9 + ADDQ DI, R9 + VPSRLQ $0x13, Y4, Y3 + VPSLLQ $0x2d, Y4, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y4, Y3 + VPSLLQ $0x03, Y4, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y0, Y2 + VPBLENDD $0xf0, Y2, Y4, Y4 + MOVQ R9, DI + RORXQ $0x29, BX, R13 + RORXQ $0x12, BX, R14 + ADDQ 24(SP), DX + ORQ R11, DI + MOVQ CX, R15 + RORXQ $0x22, R9, R12 + XORQ R14, R13 + XORQ R8, R15 + RORXQ $0x0e, BX, R14 + ANDQ BX, R15 + ADDQ DX, AX + ANDQ R10, DI + XORQ R14, R13 + XORQ R8, R15 + RORXQ $0x27, R9, R14 + ADDQ R13, R15 + XORQ R12, R14 + ADDQ R15, AX + RORXQ $0x1c, R9, R12 + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R11, R12 + ORQ R12, DI + ADDQ R14, DX + ADDQ R15, DX + ADDQ DI, DX + VPADDQ 32(BP), Y5, Y0 + VMOVDQU Y0, (SP) + VPERM2F128 $0x03, Y7, Y4, Y0 + VPALIGNR $0x08, Y7, Y0, Y0 + VPADDQ Y5, Y0, Y0 + VPERM2F128 $0x03, Y5, Y6, Y1 + VPALIGNR $0x08, Y5, Y1, Y1 + VPSRLQ $0x01, Y1, Y2 + VPSLLQ $0x3f, Y1, Y3 + VPOR Y2, Y3, Y3 + VPSRLQ $0x07, Y1, Y8 + MOVQ DX, DI + RORXQ $0x29, AX, R13 + RORXQ $0x12, AX, R14 + ADDQ (SP), R8 + ORQ R10, DI + MOVQ BX, R15 + RORXQ $0x22, DX, R12 + XORQ R14, R13 + XORQ CX, R15 + RORXQ $0x0e, AX, R14 + ANDQ AX, R15 + XORQ R14, R13 + RORXQ $0x27, DX, R14 + ADDQ R8, R11 + ANDQ R9, DI + XORQ R12, R14 + RORXQ $0x1c, DX, R12 + XORQ CX, R15 + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R10, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R8 + ADDQ R15, R11 + ADDQ R15, R8 + ADDQ DI, R8 + VPSRLQ $0x08, Y1, Y2 + VPSLLQ $0x38, Y1, Y1 + VPOR Y2, Y1, Y1 + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + VPADDQ Y1, Y0, Y0 + VPERM2F128 $0x00, Y0, Y0, Y5 + VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 + VPERM2F128 $0x11, Y4, Y4, Y2 + VPSRLQ $0x06, Y2, Y8 + MOVQ R8, DI + RORXQ $0x29, R11, R13 + RORXQ $0x12, R11, R14 + ADDQ 8(SP), CX + ORQ R9, DI + MOVQ AX, R15 + RORXQ $0x22, R8, R12 + XORQ R14, R13 + XORQ BX, R15 + RORXQ $0x0e, R11, R14 + XORQ R14, R13 + RORXQ $0x27, R8, R14 + ANDQ R11, R15 + ADDQ CX, R10 + ANDQ DX, DI + XORQ R12, R14 + RORXQ $0x1c, R8, R12 + XORQ BX, R15 + XORQ R12, R14 + MOVQ R8, R12 + ANDQ R9, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, CX + ADDQ R15, R10 + ADDQ R15, CX + ADDQ DI, CX + VPSRLQ $0x13, Y2, Y3 + VPSLLQ $0x2d, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y2, Y3 + VPSLLQ $0x03, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y5, Y5 + VPSRLQ $0x06, Y5, Y8 + MOVQ CX, DI + RORXQ $0x29, R10, R13 + ADDQ 16(SP), BX + RORXQ $0x12, R10, R14 + ORQ DX, DI + MOVQ R11, R15 + XORQ AX, R15 + RORXQ $0x22, CX, R12 + XORQ R14, R13 + ANDQ R10, R15 + RORXQ $0x0e, R10, R14 + ADDQ BX, R9 + ANDQ R8, DI + XORQ R14, R13 + RORXQ $0x27, CX, R14 + XORQ AX, R15 + XORQ R12, R14 + RORXQ $0x1c, CX, R12 + XORQ R12, R14 + MOVQ CX, R12 + ANDQ DX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, BX + ADDQ R15, R9 + ADDQ R15, BX + ADDQ DI, BX + VPSRLQ $0x13, Y5, Y3 + VPSLLQ $0x2d, Y5, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y5, Y3 + VPSLLQ $0x03, Y5, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y0, Y2 + VPBLENDD $0xf0, Y2, Y5, Y5 + MOVQ BX, DI + RORXQ $0x29, R9, R13 + RORXQ $0x12, R9, R14 + ADDQ 24(SP), AX + ORQ R8, DI + MOVQ R10, R15 + RORXQ $0x22, BX, R12 + XORQ R14, R13 + XORQ R11, R15 + RORXQ $0x0e, R9, R14 + ANDQ R9, R15 + ADDQ AX, DX + ANDQ CX, DI + XORQ R14, R13 + XORQ R11, R15 + RORXQ $0x27, BX, R14 + ADDQ R13, R15 + XORQ R12, R14 + ADDQ R15, DX + RORXQ $0x1c, BX, R12 + XORQ R12, R14 + MOVQ BX, R12 + ANDQ R8, R12 + ORQ R12, DI + ADDQ R14, AX + ADDQ R15, AX + ADDQ DI, AX + VPADDQ 64(BP), Y6, Y0 + VMOVDQU Y0, (SP) + VPERM2F128 $0x03, Y4, Y5, Y0 + VPALIGNR $0x08, Y4, Y0, Y0 + VPADDQ Y6, Y0, Y0 + VPERM2F128 $0x03, Y6, Y7, Y1 + VPALIGNR $0x08, Y6, Y1, Y1 + VPSRLQ $0x01, Y1, Y2 + VPSLLQ $0x3f, Y1, Y3 + VPOR Y2, Y3, Y3 + VPSRLQ $0x07, Y1, Y8 + MOVQ AX, DI + RORXQ $0x29, DX, R13 + RORXQ $0x12, DX, R14 + ADDQ (SP), R11 + ORQ CX, DI + MOVQ R9, R15 + RORXQ $0x22, AX, R12 + XORQ R14, R13 + XORQ R10, R15 + RORXQ $0x0e, DX, R14 + ANDQ DX, R15 + XORQ R14, R13 + RORXQ $0x27, AX, R14 + ADDQ R11, R8 + ANDQ BX, DI + XORQ R12, R14 + RORXQ $0x1c, AX, R12 + XORQ R10, R15 + XORQ R12, R14 + MOVQ AX, R12 + ANDQ CX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R11 + ADDQ R15, R8 + ADDQ R15, R11 + ADDQ DI, R11 + VPSRLQ $0x08, Y1, Y2 + VPSLLQ $0x38, Y1, Y1 + VPOR Y2, Y1, Y1 + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + VPADDQ Y1, Y0, Y0 + VPERM2F128 $0x00, Y0, Y0, Y6 + VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 + VPERM2F128 $0x11, Y5, Y5, Y2 + VPSRLQ $0x06, Y2, Y8 + MOVQ R11, DI + RORXQ $0x29, R8, R13 + RORXQ $0x12, R8, R14 + ADDQ 8(SP), R10 + ORQ BX, DI + MOVQ DX, R15 + RORXQ $0x22, R11, R12 + XORQ R14, R13 + XORQ R9, R15 + RORXQ $0x0e, R8, R14 + XORQ R14, R13 + RORXQ $0x27, R11, R14 + ANDQ R8, R15 + ADDQ R10, CX + ANDQ AX, DI + XORQ R12, R14 + RORXQ $0x1c, R11, R12 + XORQ R9, R15 + XORQ R12, R14 + MOVQ R11, R12 + ANDQ BX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R10 + ADDQ R15, CX + ADDQ R15, R10 + ADDQ DI, R10 + VPSRLQ $0x13, Y2, Y3 + VPSLLQ $0x2d, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y2, Y3 + VPSLLQ $0x03, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y6, Y6 + VPSRLQ $0x06, Y6, Y8 + MOVQ R10, DI + RORXQ $0x29, CX, R13 + ADDQ 16(SP), R9 + RORXQ $0x12, CX, R14 + ORQ AX, DI + MOVQ R8, R15 + XORQ DX, R15 + RORXQ $0x22, R10, R12 + XORQ R14, R13 + ANDQ CX, R15 + RORXQ $0x0e, CX, R14 + ADDQ R9, BX + ANDQ R11, DI + XORQ R14, R13 + RORXQ $0x27, R10, R14 + XORQ DX, R15 + XORQ R12, R14 + RORXQ $0x1c, R10, R12 + XORQ R12, R14 + MOVQ R10, R12 + ANDQ AX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R9 + ADDQ R15, BX + ADDQ R15, R9 + ADDQ DI, R9 + VPSRLQ $0x13, Y6, Y3 + VPSLLQ $0x2d, Y6, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y6, Y3 + VPSLLQ $0x03, Y6, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y0, Y2 + VPBLENDD $0xf0, Y2, Y6, Y6 + MOVQ R9, DI + RORXQ $0x29, BX, R13 + RORXQ $0x12, BX, R14 + ADDQ 24(SP), DX + ORQ R11, DI + MOVQ CX, R15 + RORXQ $0x22, R9, R12 + XORQ R14, R13 + XORQ R8, R15 + RORXQ $0x0e, BX, R14 + ANDQ BX, R15 + ADDQ DX, AX + ANDQ R10, DI + XORQ R14, R13 + XORQ R8, R15 + RORXQ $0x27, R9, R14 + ADDQ R13, R15 + XORQ R12, R14 + ADDQ R15, AX + RORXQ $0x1c, R9, R12 + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R11, R12 + ORQ R12, DI + ADDQ R14, DX + ADDQ R15, DX + ADDQ DI, DX + VPADDQ 96(BP), Y7, Y0 + VMOVDQU Y0, (SP) + ADDQ $0x80, BP + VPERM2F128 $0x03, Y5, Y6, Y0 + VPALIGNR $0x08, Y5, Y0, Y0 + VPADDQ Y7, Y0, Y0 + VPERM2F128 $0x03, Y7, Y4, Y1 + VPALIGNR $0x08, Y7, Y1, Y1 + VPSRLQ $0x01, Y1, Y2 + VPSLLQ $0x3f, Y1, Y3 + VPOR Y2, Y3, Y3 + VPSRLQ $0x07, Y1, Y8 + MOVQ DX, DI + RORXQ $0x29, AX, R13 + RORXQ $0x12, AX, R14 + ADDQ (SP), R8 + ORQ R10, DI + MOVQ BX, R15 + RORXQ $0x22, DX, R12 + XORQ R14, R13 + XORQ CX, R15 + RORXQ $0x0e, AX, R14 + ANDQ AX, R15 + XORQ R14, R13 + RORXQ $0x27, DX, R14 + ADDQ R8, R11 + ANDQ R9, DI + XORQ R12, R14 + RORXQ $0x1c, DX, R12 + XORQ CX, R15 + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R10, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R8 + ADDQ R15, R11 + ADDQ R15, R8 + ADDQ DI, R8 + VPSRLQ $0x08, Y1, Y2 + VPSLLQ $0x38, Y1, Y1 + VPOR Y2, Y1, Y1 + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + VPADDQ Y1, Y0, Y0 + VPERM2F128 $0x00, Y0, Y0, Y7 + VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 + VPERM2F128 $0x11, Y6, Y6, Y2 + VPSRLQ $0x06, Y2, Y8 + MOVQ R8, DI + RORXQ $0x29, R11, R13 + RORXQ $0x12, R11, R14 + ADDQ 8(SP), CX + ORQ R9, DI + MOVQ AX, R15 + RORXQ $0x22, R8, R12 + XORQ R14, R13 + XORQ BX, R15 + RORXQ $0x0e, R11, R14 + XORQ R14, R13 + RORXQ $0x27, R8, R14 + ANDQ R11, R15 + ADDQ CX, R10 + ANDQ DX, DI + XORQ R12, R14 + RORXQ $0x1c, R8, R12 + XORQ BX, R15 + XORQ R12, R14 + MOVQ R8, R12 + ANDQ R9, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, CX + ADDQ R15, R10 + ADDQ R15, CX + ADDQ DI, CX + VPSRLQ $0x13, Y2, Y3 + VPSLLQ $0x2d, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y2, Y3 + VPSLLQ $0x03, Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y7, Y7 + VPSRLQ $0x06, Y7, Y8 + MOVQ CX, DI + RORXQ $0x29, R10, R13 + ADDQ 16(SP), BX + RORXQ $0x12, R10, R14 + ORQ DX, DI + MOVQ R11, R15 + XORQ AX, R15 + RORXQ $0x22, CX, R12 + XORQ R14, R13 + ANDQ R10, R15 + RORXQ $0x0e, R10, R14 + ADDQ BX, R9 + ANDQ R8, DI + XORQ R14, R13 + RORXQ $0x27, CX, R14 + XORQ AX, R15 + XORQ R12, R14 + RORXQ $0x1c, CX, R12 + XORQ R12, R14 + MOVQ CX, R12 + ANDQ DX, R12 + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, BX + ADDQ R15, R9 + ADDQ R15, BX + ADDQ DI, BX + VPSRLQ $0x13, Y7, Y3 + VPSLLQ $0x2d, Y7, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $0x3d, Y7, Y3 + VPSLLQ $0x03, Y7, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPADDQ Y8, Y0, Y2 + VPBLENDD $0xf0, Y2, Y7, Y7 + MOVQ BX, DI + RORXQ $0x29, R9, R13 + RORXQ $0x12, R9, R14 + ADDQ 24(SP), AX + ORQ R8, DI + MOVQ R10, R15 + RORXQ $0x22, BX, R12 + XORQ R14, R13 + XORQ R11, R15 + RORXQ $0x0e, R9, R14 + ANDQ R9, R15 + ADDQ AX, DX + ANDQ CX, DI + XORQ R14, R13 + XORQ R11, R15 + RORXQ $0x27, BX, R14 + ADDQ R13, R15 + XORQ R12, R14 + ADDQ R15, DX + RORXQ $0x1c, BX, R12 + XORQ R12, R14 + MOVQ BX, R12 + ANDQ R8, R12 + ORQ R12, DI + ADDQ R14, AX + ADDQ R15, AX + ADDQ DI, AX + SUBQ $0x01, 32(SP) + JNE loop1 + MOVQ $0x00000002, 32(SP) + +loop2: + VPADDQ (BP), Y4, Y0 + VMOVDQU Y0, (SP) + MOVQ R9, R15 + RORXQ $0x29, DX, R13 + RORXQ $0x12, DX, R14 + XORQ R10, R15 + XORQ R14, R13 + RORXQ $0x0e, DX, R14 + ANDQ DX, R15 + XORQ R14, R13 + RORXQ $0x22, AX, R12 + XORQ R10, R15 + RORXQ $0x27, AX, R14 + MOVQ AX, DI + XORQ R12, R14 + RORXQ $0x1c, AX, R12 + ADDQ (SP), R11 + ORQ CX, DI + XORQ R12, R14 + MOVQ AX, R12 + ANDQ BX, DI + ANDQ CX, R12 + ADDQ R13, R15 + ADDQ R11, R8 + ORQ R12, DI + ADDQ R14, R11 + ADDQ R15, R8 + ADDQ R15, R11 + MOVQ DX, R15 + RORXQ $0x29, R8, R13 + RORXQ $0x12, R8, R14 + XORQ R9, R15 + XORQ R14, R13 + RORXQ $0x0e, R8, R14 + ANDQ R8, R15 + ADDQ DI, R11 + XORQ R14, R13 + RORXQ $0x22, R11, R12 + XORQ R9, R15 + RORXQ $0x27, R11, R14 + MOVQ R11, DI + XORQ R12, R14 + RORXQ $0x1c, R11, R12 + ADDQ 8(SP), R10 + ORQ BX, DI + XORQ R12, R14 + MOVQ R11, R12 + ANDQ AX, DI + ANDQ BX, R12 + ADDQ R13, R15 + ADDQ R10, CX + ORQ R12, DI + ADDQ R14, R10 + ADDQ R15, CX + ADDQ R15, R10 + MOVQ R8, R15 + RORXQ $0x29, CX, R13 + RORXQ $0x12, CX, R14 + XORQ DX, R15 + XORQ R14, R13 + RORXQ $0x0e, CX, R14 + ANDQ CX, R15 + ADDQ DI, R10 + XORQ R14, R13 + RORXQ $0x22, R10, R12 + XORQ DX, R15 + RORXQ $0x27, R10, R14 + MOVQ R10, DI + XORQ R12, R14 + RORXQ $0x1c, R10, R12 + ADDQ 16(SP), R9 + ORQ AX, DI + XORQ R12, R14 + MOVQ R10, R12 + ANDQ R11, DI + ANDQ AX, R12 + ADDQ R13, R15 + ADDQ R9, BX + ORQ R12, DI + ADDQ R14, R9 + ADDQ R15, BX + ADDQ R15, R9 + MOVQ CX, R15 + RORXQ $0x29, BX, R13 + RORXQ $0x12, BX, R14 + XORQ R8, R15 + XORQ R14, R13 + RORXQ $0x0e, BX, R14 + ANDQ BX, R15 + ADDQ DI, R9 + XORQ R14, R13 + RORXQ $0x22, R9, R12 + XORQ R8, R15 + RORXQ $0x27, R9, R14 + MOVQ R9, DI + XORQ R12, R14 + RORXQ $0x1c, R9, R12 + ADDQ 24(SP), DX + ORQ R11, DI + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R10, DI + ANDQ R11, R12 + ADDQ R13, R15 + ADDQ DX, AX + ORQ R12, DI + ADDQ R14, DX + ADDQ R15, AX + ADDQ R15, DX + ADDQ DI, DX + VPADDQ 32(BP), Y5, Y0 + VMOVDQU Y0, (SP) + ADDQ $0x40, BP + MOVQ BX, R15 + RORXQ $0x29, AX, R13 + RORXQ $0x12, AX, R14 + XORQ CX, R15 + XORQ R14, R13 + RORXQ $0x0e, AX, R14 + ANDQ AX, R15 + XORQ R14, R13 + RORXQ $0x22, DX, R12 + XORQ CX, R15 + RORXQ $0x27, DX, R14 + MOVQ DX, DI + XORQ R12, R14 + RORXQ $0x1c, DX, R12 + ADDQ (SP), R8 + ORQ R10, DI + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R9, DI + ANDQ R10, R12 + ADDQ R13, R15 + ADDQ R8, R11 + ORQ R12, DI + ADDQ R14, R8 + ADDQ R15, R11 + ADDQ R15, R8 + MOVQ AX, R15 + RORXQ $0x29, R11, R13 + RORXQ $0x12, R11, R14 + XORQ BX, R15 + XORQ R14, R13 + RORXQ $0x0e, R11, R14 + ANDQ R11, R15 + ADDQ DI, R8 + XORQ R14, R13 + RORXQ $0x22, R8, R12 + XORQ BX, R15 + RORXQ $0x27, R8, R14 + MOVQ R8, DI + XORQ R12, R14 + RORXQ $0x1c, R8, R12 + ADDQ 8(SP), CX + ORQ R9, DI + XORQ R12, R14 + MOVQ R8, R12 + ANDQ DX, DI + ANDQ R9, R12 + ADDQ R13, R15 + ADDQ CX, R10 + ORQ R12, DI + ADDQ R14, CX + ADDQ R15, R10 + ADDQ R15, CX + MOVQ R11, R15 + RORXQ $0x29, R10, R13 + RORXQ $0x12, R10, R14 + XORQ AX, R15 + XORQ R14, R13 + RORXQ $0x0e, R10, R14 + ANDQ R10, R15 + ADDQ DI, CX + XORQ R14, R13 + RORXQ $0x22, CX, R12 + XORQ AX, R15 + RORXQ $0x27, CX, R14 + MOVQ CX, DI + XORQ R12, R14 + RORXQ $0x1c, CX, R12 + ADDQ 16(SP), BX + ORQ DX, DI + XORQ R12, R14 + MOVQ CX, R12 + ANDQ R8, DI + ANDQ DX, R12 + ADDQ R13, R15 + ADDQ BX, R9 + ORQ R12, DI + ADDQ R14, BX + ADDQ R15, R9 + ADDQ R15, BX + MOVQ R10, R15 + RORXQ $0x29, R9, R13 + RORXQ $0x12, R9, R14 + XORQ R11, R15 + XORQ R14, R13 + RORXQ $0x0e, R9, R14 + ANDQ R9, R15 + ADDQ DI, BX + XORQ R14, R13 + RORXQ $0x22, BX, R12 + XORQ R11, R15 + RORXQ $0x27, BX, R14 + MOVQ BX, DI + XORQ R12, R14 + RORXQ $0x1c, BX, R12 + ADDQ 24(SP), AX + ORQ R8, DI + XORQ R12, R14 + MOVQ BX, R12 + ANDQ CX, DI + ANDQ R8, R12 + ADDQ R13, R15 + ADDQ AX, DX + ORQ R12, DI + ADDQ R14, AX + ADDQ R15, DX + ADDQ R15, AX + ADDQ DI, AX + VMOVDQU Y6, Y4 + VMOVDQU Y7, Y5 + SUBQ $0x01, 32(SP) + JNE loop2 + ADDQ (SI), AX + MOVQ AX, (SI) + ADDQ 8(SI), BX + MOVQ BX, 8(SI) + ADDQ 16(SI), CX + MOVQ CX, 16(SI) + ADDQ 24(SI), R8 + MOVQ R8, 24(SI) + ADDQ 32(SI), DX + MOVQ DX, 32(SI) + ADDQ 40(SI), R9 + MOVQ R9, 40(SI) + ADDQ 48(SI), R10 + MOVQ R10, 48(SI) + ADDQ 56(SI), R11 + MOVQ R11, 56(SI) + MOVQ 40(SP), DI + ADDQ $0x80, DI + CMPQ DI, 48(SP) + JNE loop0 + +done_hash: + VZEROUPPER + RET + +DATA PSHUFFLE_BYTE_FLIP_MASK<>+0(SB)/8, $0x0001020304050607 +DATA PSHUFFLE_BYTE_FLIP_MASK<>+8(SB)/8, $0x08090a0b0c0d0e0f +DATA PSHUFFLE_BYTE_FLIP_MASK<>+16(SB)/8, $0x1011121314151617 +DATA PSHUFFLE_BYTE_FLIP_MASK<>+24(SB)/8, $0x18191a1b1c1d1e1f +GLOBL PSHUFFLE_BYTE_FLIP_MASK<>(SB), RODATA|NOPTR, $32 + +DATA MASK_YMM_LO<>+0(SB)/8, $0x0000000000000000 +DATA MASK_YMM_LO<>+8(SB)/8, $0x0000000000000000 +DATA MASK_YMM_LO<>+16(SB)/8, $0xffffffffffffffff +DATA MASK_YMM_LO<>+24(SB)/8, $0xffffffffffffffff +GLOBL MASK_YMM_LO<>(SB), RODATA|NOPTR, $32 diff --git a/crypto/internal/fips140/sha512/sha512block_arm64.go b/crypto/internal/fips140/sha512/sha512block_arm64.go new file mode 100644 index 00000000000..e58277e96a3 --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512block_arm64.go @@ -0,0 +1,29 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha512 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useSHA512 = cpu.ARM64HasSHA512 + +func init() { + impl.Register("sha512", "Armv8.2", &useSHA512) +} + +//go:noescape +func blockSHA512(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useSHA512 { + blockSHA512(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha512/sha512block_arm64.s b/crypto/internal/fips140/sha512/sha512block_arm64.s similarity index 98% rename from crypto/sha512/sha512block_arm64.s rename to crypto/internal/fips140/sha512/sha512block_arm64.s index 25f3dbfe43d..cabe262548c 100644 --- a/crypto/sha512/sha512block_arm64.s +++ b/crypto/internal/fips140/sha512/sha512block_arm64.s @@ -40,12 +40,12 @@ VADD i3.D2, i1.D2, i4.D2 \ SHA512H2 i0.D2, i1, i3 -// func blockAsm(dig *digest, p []byte) -TEXT ·blockAsm(SB),NOSPLIT,$0 +// func blockSHA512(dig *Digest, p []byte) +TEXT ·blockSHA512(SB),NOSPLIT,$0 MOVD dig+0(FP), R0 MOVD p_base+8(FP), R1 MOVD p_len+16(FP), R2 - MOVD ·_K+0(SB), R3 + MOVD $·_K+0(SB), R3 // long enough to prefetch PRFM (R3), PLDL3KEEP diff --git a/crypto/sha512/sha512block_decl.go b/crypto/internal/fips140/sha512/sha512block_asm.go similarity index 64% rename from crypto/sha512/sha512block_decl.go rename to crypto/internal/fips140/sha512/sha512block_asm.go index b8a7854e4dd..532345108f8 100644 --- a/crypto/sha512/sha512block_decl.go +++ b/crypto/internal/fips140/sha512/sha512block_asm.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (loong64 || ppc64 || ppc64le || riscv64 || s390x) && !purego +//go:build (loong64 || riscv64) && !purego package sha512 //go:noescape -func block(dig *digest, p []byte) +func block(dig *Digest, p []byte) diff --git a/crypto/sha512/sha512block_loong64.s b/crypto/internal/fips140/sha512/sha512block_loong64.s similarity index 96% rename from crypto/sha512/sha512block_loong64.s rename to crypto/internal/fips140/sha512/sha512block_loong64.s index e508f23c58d..f65d563ca34 100644 --- a/crypto/sha512/sha512block_loong64.s +++ b/crypto/internal/fips140/sha512/sha512block_loong64.s @@ -18,7 +18,7 @@ // W[i] = M[i]; for 0 <= i <= 15 #define LOAD0(index) \ MOVV (index*8)(R5), REGTMP4; \ - WORD $0x3ce7; \ //REVBV REGTMP4, REGTMP4 + REVBV REGTMP4, REGTMP4; \ MOVV REGTMP4, (index*8)(R3) // W[i] = SIGMA1(W[i-2]) + W[i-7] + SIGMA0(W[i-15]) + W[i-16]; for 16 <= i <= 79 @@ -50,38 +50,37 @@ // T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + K[i] + W[i] // BIGSIGMA1(x) = ROTR(14,x) XOR ROTR(18,x) XOR ROTR(41,x) // Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +// = ((y XOR z) AND x) XOR z // Calculate T1 in REGTMP4 #define SHA512T1(const, e, f, g, h) \ ADDV $const, h; \ ADDV REGTMP4, h; \ - ROTRV $14, e, REGTMP4; \ + ROTRV $14, e, REGTMP5; \ ROTRV $18, e, REGTMP; \ ROTRV $41, e, REGTMP3; \ - AND f, e, REGTMP2; \ - XOR REGTMP, REGTMP4; \ - MOVV $0xffffffffffffffff, REGTMP; \ - XOR REGTMP4, REGTMP3; \ - XOR REGTMP, e, REGTMP5; \ + XOR f, g, REGTMP2; \ + XOR REGTMP, REGTMP5; \ + AND e, REGTMP2; \ + XOR REGTMP5, REGTMP3; \ + XOR g, REGTMP2; \ ADDV REGTMP3, h; \ - AND g, REGTMP5; \ - XOR REGTMP2, REGTMP5; \ - ADDV h, REGTMP5, REGTMP4 + ADDV h, REGTMP2, REGTMP4 // T2 = BIGSIGMA0(a) + Maj(a, b, c) // BIGSIGMA0(x) = ROTR(28,x) XOR ROTR(34,x) XOR ROTR(39,x) // Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +// = ((y XOR z) AND x) XOR (y AND z) // Calculate T2 in REGTMP1 #define SHA512T2(a, b, c) \ ROTRV $28, a, REGTMP5; \ - AND b, c, REGTMP1; \ ROTRV $34, a, REGTMP3; \ - AND c, a, REGTMP; \ - XOR REGTMP3, REGTMP5; \ - XOR REGTMP, REGTMP1; \ ROTRV $39, a, REGTMP2; \ - AND a, b, REGTMP3; \ - XOR REGTMP3, REGTMP1; \ + XOR b, c, REGTMP; \ + AND b, c, REGTMP1; \ + XOR REGTMP3, REGTMP5; \ + AND REGTMP, a, REGTMP; \ XOR REGTMP2, REGTMP5; \ + XOR REGTMP, REGTMP1; \ ADDV REGTMP5, REGTMP1 // Calculate T1 and T2, then e = d + T1 and a = T1 + T2. @@ -104,7 +103,7 @@ // the frame size used for data expansion is 128 bytes. // See the definition of the macro LOAD1 above (8 bytes * 16 entries). // -// func block(dig *digest, p []byte) +// func block(dig *Digest, p []byte) TEXT ·block(SB),NOSPLIT,$128-32 MOVV p_len+16(FP), R6 MOVV p_base+8(FP), R5 diff --git a/crypto/sha512/sha512block_generic.go b/crypto/internal/fips140/sha512/sha512block_noasm.go similarity index 89% rename from crypto/sha512/sha512block_generic.go rename to crypto/internal/fips140/sha512/sha512block_noasm.go index 5d556606ed6..a1051ca2db0 100644 --- a/crypto/sha512/sha512block_generic.go +++ b/crypto/internal/fips140/sha512/sha512block_noasm.go @@ -6,6 +6,6 @@ package sha512 -func block(dig *digest, p []byte) { +func block(dig *Digest, p []byte) { blockGeneric(dig, p) } diff --git a/crypto/internal/fips140/sha512/sha512block_ppc64x.go b/crypto/internal/fips140/sha512/sha512block_ppc64x.go new file mode 100644 index 00000000000..c39fb7e9301 --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512block_ppc64x.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64 || ppc64le) && !purego + +package sha512 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +// The POWER architecture doesn't have a way to turn off SHA-512 support at +// runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG knob for +// that. It's intentionally only checked at init() time, to avoid the +// performance overhead of checking it on every block. +var ppc64sha512 = godebug.Value("#ppc64sha512") != "off" + +func init() { + impl.Register("sha512", "POWER8", &ppc64sha512) +} + +//go:noescape +func blockPOWER(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if ppc64sha512 { + blockPOWER(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha512/sha512block_ppc64x.s b/crypto/internal/fips140/sha512/sha512block_ppc64x.s similarity index 99% rename from crypto/sha512/sha512block_ppc64x.s rename to crypto/internal/fips140/sha512/sha512block_ppc64x.s index 87aab80903c..fd2c47bc7e3 100644 --- a/crypto/sha512/sha512block_ppc64x.s +++ b/crypto/internal/fips140/sha512/sha512block_ppc64x.s @@ -304,8 +304,8 @@ GLOBL ·kcon(SB), RODATA, $1312 VADDUDM S0, h, h; \ VADDUDM s1, xj, xj -// func block(dig *digest, p []byte) -TEXT ·block(SB),0,$0-32 +// func blockPOWER(dig *Digest, p []byte) +TEXT ·blockPOWER(SB),0,$0-32 MOVD dig+0(FP), CTX MOVD p_base+8(FP), INP MOVD p_len+16(FP), LEN diff --git a/crypto/sha512/sha512block_riscv64.s b/crypto/internal/fips140/sha512/sha512block_riscv64.s similarity index 96% rename from crypto/sha512/sha512block_riscv64.s rename to crypto/internal/fips140/sha512/sha512block_riscv64.s index 7dcb0f80d0a..f25ed62237b 100644 --- a/crypto/sha512/sha512block_riscv64.s +++ b/crypto/internal/fips140/sha512/sha512block_riscv64.s @@ -100,47 +100,46 @@ // T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt // BIGSIGMA1(x) = ROTR(14,x) XOR ROTR(18,x) XOR ROTR(41,x) // Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +// = ((y XOR z) AND x) XOR z #define SHA512T1(index, e, f, g, h) \ MOV (index*8)(X18), X8; \ ADD X5, h; \ ROR $14, e, X6; \ ADD X8, h; \ ROR $18, e, X7; \ - XOR X7, X6; \ ROR $41, e, X8; \ + XOR X7, X6; \ + XOR f, g, X5; \ XOR X8, X6; \ + AND e, X5; \ ADD X6, h; \ - AND e, f, X5; \ - NOT e, X7; \ - AND g, X7; \ - XOR X7, X5; \ + XOR g, X5; \ ADD h, X5 // Calculate T2 in X6. // T2 = BIGSIGMA0(a) + Maj(a, b, c) // BIGSIGMA0(x) = ROTR(28,x) XOR ROTR(34,x) XOR ROTR(39,x) // Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +// = ((y XOR z) AND x) XOR (y AND z) #define SHA512T2(a, b, c) \ ROR $28, a, X6; \ ROR $34, a, X7; \ - XOR X7, X6; \ ROR $39, a, X8; \ + XOR X7, X6; \ + XOR b, c, X9; \ + AND b, c, X7; \ + AND a, X9; \ XOR X8, X6; \ - AND a, b, X7; \ - AND a, c, X8; \ - XOR X8, X7; \ - AND b, c, X9; \ - XOR X9, X7; \ - ADD X7, X6 + XOR X7, X9; \ + ADD X9, X6 // Calculate T1 and T2, then e = d + T1 and a = T1 + T2. // The values for e and a are stored in d and h, ready for rotation. #define SHA512ROUND(index, a, b, c, d, e, f, g, h) \ SHA512T1(index, e, f, g, h); \ SHA512T2(a, b, c); \ - MOV X6, h; \ ADD X5, d; \ - ADD X5, h + ADD X6, X5, h #define SHA512ROUND0(index, a, b, c, d, e, f, g, h) \ MSGSCHEDULE0(index); \ @@ -150,7 +149,7 @@ MSGSCHEDULE1(index); \ SHA512ROUND(index, a, b, c, d, e, f, g, h) -// func block(dig *digest, p []byte) +// func block(dig *Digest, p []byte) TEXT ·block(SB),0,$128-32 MOV p_base+8(FP), X29 MOV p_len+16(FP), X30 @@ -160,7 +159,7 @@ TEXT ·block(SB),0,$128-32 ADD X29, X30, X28 BEQ X28, X29, end - MOV ·_K(SB), X18 // const table + MOV $·_K(SB), X18 // const table ADD $8, X2, X19 // message schedule MOV dig+0(FP), X20 diff --git a/crypto/internal/fips140/sha512/sha512block_s390x.go b/crypto/internal/fips140/sha512/sha512block_s390x.go new file mode 100644 index 00000000000..61a8935ce99 --- /dev/null +++ b/crypto/internal/fips140/sha512/sha512block_s390x.go @@ -0,0 +1,31 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package sha512 + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useSHA512 = cpu.S390XHasSHA512 + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf + impl.Register("sha512", "CPACF", &useSHA512) +} + +//go:noescape +func blockS390X(dig *Digest, p []byte) + +func block(dig *Digest, p []byte) { + if useSHA512 { + blockS390X(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha512/sha512block_s390x.s b/crypto/internal/fips140/sha512/sha512block_s390x.s similarity index 73% rename from crypto/sha512/sha512block_s390x.s rename to crypto/internal/fips140/sha512/sha512block_s390x.s index 230bd414d38..5e943ed11fc 100644 --- a/crypto/sha512/sha512block_s390x.s +++ b/crypto/internal/fips140/sha512/sha512block_s390x.s @@ -6,17 +6,12 @@ #include "textflag.h" -// func block(dig *digest, p []byte) -TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 - MOVBZ ·useAsm(SB), R4 +// func blockS390X(dig *Digest, p []byte) +TEXT ·blockS390X(SB), NOSPLIT|NOFRAME, $0-32 LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) MOVBZ $3, R0 // SHA-512 function code - CMPBEQ R4, $0, generic loop: KIMD R0, R2 // compute intermediate message digest (KIMD) BVS loop // continue if interrupted RET - -generic: - BR ·blockGeneric(SB) diff --git a/crypto/internal/fips140/ssh/kdf.go b/crypto/internal/fips140/ssh/kdf.go new file mode 100644 index 00000000000..9bc3ba14460 --- /dev/null +++ b/crypto/internal/fips140/ssh/kdf.go @@ -0,0 +1,56 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ssh implements the SSH KDF as specified in RFC 4253, +// Section 7.2 and allowed by SP 800-135 Revision 1. +package ssh + +import ( + "github.com/runZeroInc/excrypto/hash" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" +) + +type Direction struct { + ivTag []byte + keyTag []byte + macKeyTag []byte +} + +var ServerKeys, ClientKeys Direction + +func init() { + ServerKeys = Direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} + ClientKeys = Direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} +} + +func Keys[Hash hash.Hash](hash func() Hash, d Direction, + K, H, sessionID []byte, + ivKeyLen, keyLen, macKeyLen int, +) (ivKey, key, macKey []byte) { + + h := hash() + generateKeyMaterial := func(tag []byte, length int) []byte { + var key []byte + for len(key) < length { + h.Reset() + h.Write(K) + h.Write(H) + if len(key) == 0 { + h.Write(tag) + h.Write(sessionID) + } else { + h.Write(key) + } + key = h.Sum(key) + } + return key[:length] + } + + ivKey = generateKeyMaterial(d.ivTag, ivKeyLen) + key = generateKeyMaterial(d.keyTag, keyLen) + macKey = generateKeyMaterial(d.macKeyTag, macKeyLen) + + return +} diff --git a/crypto/internal/fips140/subtle/constant_time.go b/crypto/internal/fips140/subtle/constant_time.go new file mode 100644 index 00000000000..cfaa1aefe58 --- /dev/null +++ b/crypto/internal/fips140/subtle/constant_time.go @@ -0,0 +1,97 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +import ( + "math/bits" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// ConstantTimeCompare returns 1 if the two slices, x and y, have equal contents +// and 0 otherwise. The time taken is a function of the length of the slices and +// is independent of the contents. If the lengths of x and y do not match it +// returns 0 immediately. +func ConstantTimeCompare(x, y []byte) int { + if len(x) != len(y) { + return 0 + } + + var v byte + + for i := 0; i < len(x); i++ { + v |= x[i] ^ y[i] + } + + return ConstantTimeByteEq(v, 0) +} + +// ConstantTimeLessOrEqBytes returns 1 if x <= y and 0 otherwise. The comparison +// is lexigraphical, or big-endian. The time taken is a function of the length of +// the slices and is independent of the contents. If the lengths of x and y do not +// match it returns 0 immediately. +func ConstantTimeLessOrEqBytes(x, y []byte) int { + if len(x) != len(y) { + return 0 + } + + // Do a constant time subtraction chain y - x. + // If there is no borrow at the end, then x <= y. + var b uint64 + for len(x) > 8 { + x0 := byteorder.BEUint64(x[len(x)-8:]) + y0 := byteorder.BEUint64(y[len(y)-8:]) + _, b = bits.Sub64(y0, x0, b) + x = x[:len(x)-8] + y = y[:len(y)-8] + } + if len(x) > 0 { + xb := make([]byte, 8) + yb := make([]byte, 8) + copy(xb[8-len(x):], x) + copy(yb[8-len(y):], y) + x0 := byteorder.BEUint64(xb) + y0 := byteorder.BEUint64(yb) + _, b = bits.Sub64(y0, x0, b) + } + return int(b ^ 1) +} + +// ConstantTimeSelect returns x if v == 1 and y if v == 0. +// Its behavior is undefined if v takes any other value. +func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y } + +// ConstantTimeByteEq returns 1 if x == y and 0 otherwise. +func ConstantTimeByteEq(x, y uint8) int { + return int((uint32(x^y) - 1) >> 31) +} + +// ConstantTimeEq returns 1 if x == y and 0 otherwise. +func ConstantTimeEq(x, y int32) int { + return int((uint64(uint32(x^y)) - 1) >> 63) +} + +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. +func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + + xmask := byte(v - 1) + ymask := byte(^(v - 1)) + for i := 0; i < len(x); i++ { + x[i] = x[i]&xmask | y[i]&ymask + } +} + +// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. +// Its behavior is undefined if x or y are negative or > 2**31 - 1. +func ConstantTimeLessOrEq(x, y int) int { + x32 := int32(x) + y32 := int32(y) + return int(((x32 - y32 - 1) >> 31) & 1) +} diff --git a/crypto/internal/fips140/subtle/constant_time_test.go b/crypto/internal/fips140/subtle/constant_time_test.go new file mode 100644 index 00000000000..9e9fc620396 --- /dev/null +++ b/crypto/internal/fips140/subtle/constant_time_test.go @@ -0,0 +1,105 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +import ( + "bytes" + "math/rand/v2" + "testing" + "time" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +func TestConstantTimeLessOrEqBytes(t *testing.T) { + seed := make([]byte, 32) + byteorder.BEPutUint64(seed, uint64(time.Now().UnixNano())) + r := rand.NewChaCha8([32]byte(seed)) + for l := range 20 { + a := make([]byte, l) + b := make([]byte, l) + empty := make([]byte, l) + r.Read(a) + r.Read(b) + exp := 0 + if bytes.Compare(a, b) <= 0 { + exp = 1 + } + if got := ConstantTimeLessOrEqBytes(a, b); got != exp { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want %d", a, b, got, exp) + } + exp = 0 + if bytes.Compare(b, a) <= 0 { + exp = 1 + } + if got := ConstantTimeLessOrEqBytes(b, a); got != exp { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want %d", b, a, got, exp) + } + if got := ConstantTimeLessOrEqBytes(empty, a); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", empty, a, got) + } + if got := ConstantTimeLessOrEqBytes(empty, b); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", empty, b, got) + } + if got := ConstantTimeLessOrEqBytes(a, a); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", a, a, got) + } + if got := ConstantTimeLessOrEqBytes(b, b); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", b, b, got) + } + if got := ConstantTimeLessOrEqBytes(empty, empty); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", empty, empty, got) + } + if l == 0 { + continue + } + max := make([]byte, l) + for i := range max { + max[i] = 0xff + } + if got := ConstantTimeLessOrEqBytes(a, max); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", a, max, got) + } + if got := ConstantTimeLessOrEqBytes(b, max); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", b, max, got) + } + if got := ConstantTimeLessOrEqBytes(empty, max); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", empty, max, got) + } + if got := ConstantTimeLessOrEqBytes(max, max); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", max, max, got) + } + aPlusOne := make([]byte, l) + copy(aPlusOne, a) + for i := l - 1; i >= 0; i-- { + if aPlusOne[i] == 0xff { + aPlusOne[i] = 0 + continue + } + aPlusOne[i]++ + if got := ConstantTimeLessOrEqBytes(a, aPlusOne); got != 1 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 1", a, aPlusOne, got) + } + if got := ConstantTimeLessOrEqBytes(aPlusOne, a); got != 0 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 0", aPlusOne, a, got) + } + break + } + shorter := make([]byte, l-1) + copy(shorter, a) + if got := ConstantTimeLessOrEqBytes(a, shorter); got != 0 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 0", a, shorter, got) + } + if got := ConstantTimeLessOrEqBytes(shorter, a); got != 0 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 0", shorter, a, got) + } + if got := ConstantTimeLessOrEqBytes(b, shorter); got != 0 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 0", b, shorter, got) + } + if got := ConstantTimeLessOrEqBytes(shorter, b); got != 0 { + t.Errorf("ConstantTimeLessOrEqBytes(%x, %x) = %d, want 0", shorter, b, got) + } + } +} diff --git a/crypto/internal/fips140/subtle/xor.go b/crypto/internal/fips140/subtle/xor.go new file mode 100644 index 00000000000..e0e9c38f4c9 --- /dev/null +++ b/crypto/internal/fips140/subtle/xor.go @@ -0,0 +1,30 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +import "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias" + +// XORBytes sets dst[i] = x[i] ^ y[i] for all i < n = min(len(x), len(y)), +// returning n, the number of bytes written to dst. +// +// If dst does not have length at least n, +// XORBytes panics without writing anything to dst. +// +// dst and x or y may overlap exactly or not at all, +// otherwise XORBytes may panic. +func XORBytes(dst, x, y []byte) int { + n := min(len(x), len(y)) + if n == 0 { + return 0 + } + if n > len(dst) { + panic("subtle.XORBytes: dst too short") + } + if alias.InexactOverlap(dst[:n], x[:n]) || alias.InexactOverlap(dst[:n], y[:n]) { + panic("subtle.XORBytes: invalid overlap") + } + xorBytes(&dst[0], &x[0], &y[0], n) // arch-specific + return n +} diff --git a/crypto/subtle/xor_amd64.s b/crypto/internal/fips140/subtle/xor_amd64.s similarity index 100% rename from crypto/subtle/xor_amd64.s rename to crypto/internal/fips140/subtle/xor_amd64.s diff --git a/crypto/subtle/xor_arm64.s b/crypto/internal/fips140/subtle/xor_arm64.s similarity index 100% rename from crypto/subtle/xor_arm64.s rename to crypto/internal/fips140/subtle/xor_arm64.s diff --git a/crypto/subtle/xor_ppc64x.go b/crypto/internal/fips140/subtle/xor_asm.go similarity index 67% rename from crypto/subtle/xor_ppc64x.go rename to crypto/internal/fips140/subtle/xor_asm.go index 760463c7e50..b07239da3e3 100644 --- a/crypto/subtle/xor_ppc64x.go +++ b/crypto/internal/fips140/subtle/xor_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (ppc64 || ppc64le) && !purego +//go:build (amd64 || arm64 || mips || mipsle || mips64 || mips64le || ppc64 || ppc64le || riscv64) && !purego package subtle diff --git a/crypto/subtle/xor_generic.go b/crypto/internal/fips140/subtle/xor_generic.go similarity index 92% rename from crypto/subtle/xor_generic.go rename to crypto/internal/fips140/subtle/xor_generic.go index e575c356960..ed484bc630e 100644 --- a/crypto/subtle/xor_generic.go +++ b/crypto/internal/fips140/subtle/xor_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!amd64 && !arm64 && !loong64 && !ppc64 && !ppc64le) || purego +//go:build (!amd64 && !arm64 && !loong64 && !mips && !mipsle && !mips64 && !mips64le && !ppc64 && !ppc64le && !riscv64) || purego package subtle diff --git a/crypto/internal/fips140/subtle/xor_loong64.go b/crypto/internal/fips140/subtle/xor_loong64.go new file mode 100644 index 00000000000..3f8225da924 --- /dev/null +++ b/crypto/internal/fips140/subtle/xor_loong64.go @@ -0,0 +1,39 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package subtle + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/cpu" + "github.com/runZeroInc/excrypto/crypto/internal/impl" +) + +var useLSX = cpu.LOONG64HasLSX +var useLASX = cpu.LOONG64HasLASX + +func init() { + impl.Register("subtle", "LSX", &useLSX) + impl.Register("subtle", "LASX", &useLASX) +} + +//go:noescape +func xorBytesBasic(dst, a, b *byte, n int) + +//go:noescape +func xorBytesLSX(dst, a, b *byte, n int) + +//go:noescape +func xorBytesLASX(dst, a, b *byte, n int) + +func xorBytes(dst, a, b *byte, n int) { + if useLASX { + xorBytesLASX(dst, a, b, n) + } else if useLSX { + xorBytesLSX(dst, a, b, n) + } else { + xorBytesBasic(dst, a, b, n) + } +} diff --git a/crypto/internal/fips140/subtle/xor_loong64.s b/crypto/internal/fips140/subtle/xor_loong64.s new file mode 100644 index 00000000000..36c18a62777 --- /dev/null +++ b/crypto/internal/fips140/subtle/xor_loong64.s @@ -0,0 +1,409 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +#define SMALL_TAIL \ + SGTU $2, R7, R8; \ + BNE R8, xor_1; \ + SGTU $4, R7, R8; \ + BNE R8, xor_2; \ + SGTU $8, R7, R8; \ + BNE R8, xor_4; \ + SGTU $16, R7, R8; \ + BNE R8, xor_8; \ + +#define SMALL \ +xor_8_check:; \ + SGTU $8, R7, R8; \ + BNE R8, xor_4_check; \ +xor_8:; \ + SUBV $8, R7; \ + MOVV (R5), R10; \ + MOVV (R6), R11; \ + XOR R10, R11; \ + MOVV R11, (R4); \ + ADDV $8, R5; \ + ADDV $8, R6; \ + ADDV $8, R4; \ + BEQ R7, R0, end; \ +xor_4_check:; \ + SGTU $4, R7, R8; \ + BNE R8, xor_2_check; \ +xor_4:; \ + SUBV $4, R7; \ + MOVW (R5), R10; \ + MOVW (R6), R11; \ + XOR R10, R11; \ + MOVW R11, (R4); \ + ADDV $4, R5; \ + ADDV $4, R6; \ + ADDV $4, R4; \ + BEQ R7, R0, end; \ +xor_2_check:; \ + SGTU $2, R7, R8; \ + BNE R8, xor_1; \ +xor_2:; \ + SUBV $2, R7; \ + MOVH (R5), R10; \ + MOVH (R6), R11; \ + XOR R10, R11; \ + MOVH R11, (R4); \ + ADDV $2, R5; \ + ADDV $2, R6; \ + ADDV $2, R4; \ + BEQ R7, R0, end; \ +xor_1:; \ + MOVB (R5), R10; \ + MOVB (R6), R11; \ + XOR R10, R11; \ + MOVB R11, (R4); \ + +// func xorBytesBasic(dst, a, b *byte, n int) +TEXT ·xorBytesBasic(SB), NOSPLIT, $0 + MOVV dst+0(FP), R4 + MOVV a+8(FP), R5 + MOVV b+16(FP), R6 + MOVV n+24(FP), R7 + + SMALL_TAIL + +xor_64_check: + SGTU $64, R7, R8 + BNE R8, xor_32_check +xor_64_loop: + SUBV $64, R7 + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV 16(R5), R12 + MOVV 24(R5), R13 + MOVV (R6), R14 + MOVV 8(R6), R15 + MOVV 16(R6), R16 + MOVV 24(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, (R4) + MOVV R15, 8(R4) + MOVV R16, 16(R4) + MOVV R17, 24(R4) + MOVV 32(R5), R10 + MOVV 40(R5), R11 + MOVV 48(R5), R12 + MOVV 56(R5), R13 + MOVV 32(R6), R14 + MOVV 40(R6), R15 + MOVV 48(R6), R16 + MOVV 56(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, 32(R4) + MOVV R15, 40(R4) + MOVV R16, 48(R4) + MOVV R17, 56(R4) + SGTU $64, R7, R8 + ADDV $64, R5 + ADDV $64, R6 + ADDV $64, R4 + BEQ R8, xor_64_loop + BEQ R7, end + +xor_32_check: + SGTU $32, R7, R8 + BNE R8, xor_16_check +xor_32: + SUBV $32, R7 + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV 16(R5), R12 + MOVV 24(R5), R13 + MOVV (R6), R14 + MOVV 8(R6), R15 + MOVV 16(R6), R16 + MOVV 24(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, (R4) + MOVV R15, 8(R4) + MOVV R16, 16(R4) + MOVV R17, 24(R4) + ADDV $32, R5 + ADDV $32, R6 + ADDV $32, R4 + BEQ R7, R0, end + +xor_16_check: + SGTU $16, R7, R8 + BNE R8, xor_8_check +xor_16: + SUBV $16, R7 + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV (R6), R12 + MOVV 8(R6), R13 + XOR R10, R12 + XOR R11, R13 + MOVV R12, (R4) + MOVV R13, 8(R4) + ADDV $16, R5 + ADDV $16, R6 + ADDV $16, R4 + BEQ R7, R0, end + + SMALL +end: + RET + +// func xorBytesLSX(dst, a, b *byte, n int) +TEXT ·xorBytesLSX(SB), NOSPLIT, $0 + MOVV dst+0(FP), R4 + MOVV a+8(FP), R5 + MOVV b+16(FP), R6 + MOVV n+24(FP), R7 + + SMALL_TAIL + +xor_128_lsx_check: + SGTU $128, R7, R8 + BNE R8, xor_64_lsx_check +xor_128_lsx_loop: + SUBV $128, R7 + VMOVQ (R5), V0 + VMOVQ 16(R5), V1 + VMOVQ 32(R5), V2 + VMOVQ 48(R5), V3 + VMOVQ 64(R5), V4 + VMOVQ 80(R5), V5 + VMOVQ 96(R5), V6 + VMOVQ 112(R5), V7 + VMOVQ (R6), V8 + VMOVQ 16(R6), V9 + VMOVQ 32(R6), V10 + VMOVQ 48(R6), V11 + VMOVQ 64(R6), V12 + VMOVQ 80(R6), V13 + VMOVQ 96(R6), V14 + VMOVQ 112(R6), V15 + VXORV V0, V8, V8 + VXORV V1, V9, V9 + VXORV V2, V10, V10 + VXORV V3, V11, V11 + VXORV V4, V12, V12 + VXORV V5, V13, V13 + VXORV V6, V14, V14 + VXORV V7, V15, V15 + VMOVQ V8, (R4) + VMOVQ V9, 16(R4) + VMOVQ V10, 32(R4) + VMOVQ V11, 48(R4) + VMOVQ V12, 64(R4) + VMOVQ V13, 80(R4) + VMOVQ V14, 96(R4) + VMOVQ V15, 112(R4) + SGTU $128, R7, R8 + ADDV $128, R5 + ADDV $128, R6 + ADDV $128, R4 + BEQ R8, xor_128_lsx_loop + BEQ R7, end + +xor_64_lsx_check: + SGTU $64, R7, R8 + BNE R8, xor_32_lsx_check +xor_64_lsx: + SUBV $64, R7 + VMOVQ (R5), V0 + VMOVQ 16(R5), V1 + VMOVQ 32(R5), V2 + VMOVQ 48(R5), V3 + VMOVQ (R6), V4 + VMOVQ 16(R6), V5 + VMOVQ 32(R6), V6 + VMOVQ 48(R6), V7 + VXORV V0, V4, V4 + VXORV V1, V5, V5 + VXORV V2, V6, V6 + VXORV V3, V7, V7 + VMOVQ V4, (R4) + VMOVQ V5, 16(R4) + VMOVQ V6, 32(R4) + VMOVQ V7, 48(R4) + ADDV $64, R5 + ADDV $64, R6 + ADDV $64, R4 + BEQ R7, end + +xor_32_lsx_check: + SGTU $32, R7, R8 + BNE R8, xor_16_lsx_check +xor_32_lsx: + SUBV $32, R7 + VMOVQ (R5), V0 + VMOVQ 16(R5), V1 + VMOVQ (R6), V2 + VMOVQ 16(R6), V3 + VXORV V0, V2, V2 + VXORV V1, V3, V3 + VMOVQ V2, (R4) + VMOVQ V3, 16(R4) + ADDV $32, R5 + ADDV $32, R6 + ADDV $32, R4 + BEQ R7, end + +xor_16_lsx_check: + SGTU $16, R7, R8 + BNE R8, xor_8_check +xor_16_lsx: + SUBV $16, R7 + VMOVQ (R5), V0 + VMOVQ (R6), V1 + VXORV V0, V1, V1 + VMOVQ V1, (R4) + ADDV $16, R5 + ADDV $16, R6 + ADDV $16, R4 + BEQ R7, end + + SMALL +end: + RET + +// func xorBytesLASX(dst, a, b *byte, n int) +TEXT ·xorBytesLASX(SB), NOSPLIT, $0 + MOVV dst+0(FP), R4 + MOVV a+8(FP), R5 + MOVV b+16(FP), R6 + MOVV n+24(FP), R7 + + SMALL_TAIL + +xor_256_lasx_check: + SGTU $256, R7, R8 + BNE R8, xor_128_lasx_check +xor_256_lasx_loop: + SUBV $256, R7 + XVMOVQ (R5), X0 + XVMOVQ 32(R5), X1 + XVMOVQ 64(R5), X2 + XVMOVQ 96(R5), X3 + XVMOVQ 128(R5), X4 + XVMOVQ 160(R5), X5 + XVMOVQ 192(R5), X6 + XVMOVQ 224(R5), X7 + XVMOVQ (R6), X8 + XVMOVQ 32(R6), X9 + XVMOVQ 64(R6), X10 + XVMOVQ 96(R6), X11 + XVMOVQ 128(R6), X12 + XVMOVQ 160(R6), X13 + XVMOVQ 192(R6), X14 + XVMOVQ 224(R6), X15 + XVXORV X0, X8, X8 + XVXORV X1, X9, X9 + XVXORV X2, X10, X10 + XVXORV X3, X11, X11 + XVXORV X4, X12, X12 + XVXORV X5, X13, X13 + XVXORV X6, X14, X14 + XVXORV X7, X15, X15 + XVMOVQ X8, (R4) + XVMOVQ X9, 32(R4) + XVMOVQ X10, 64(R4) + XVMOVQ X11, 96(R4) + XVMOVQ X12, 128(R4) + XVMOVQ X13, 160(R4) + XVMOVQ X14, 192(R4) + XVMOVQ X15, 224(R4) + SGTU $256, R7, R8 + ADDV $256, R5 + ADDV $256, R6 + ADDV $256, R4 + BEQ R8, xor_256_lasx_loop + BEQ R7, end + +xor_128_lasx_check: + SGTU $128, R7, R8 + BNE R8, xor_64_lasx_check +xor_128_lasx: + SUBV $128, R7 + XVMOVQ (R5), X0 + XVMOVQ 32(R5), X1 + XVMOVQ 64(R5), X2 + XVMOVQ 96(R5), X3 + XVMOVQ (R6), X4 + XVMOVQ 32(R6), X5 + XVMOVQ 64(R6), X6 + XVMOVQ 96(R6), X7 + XVXORV X0, X4, X4 + XVXORV X1, X5, X5 + XVXORV X2, X6, X6 + XVXORV X3, X7, X7 + XVMOVQ X4, (R4) + XVMOVQ X5, 32(R4) + XVMOVQ X6, 64(R4) + XVMOVQ X7, 96(R4) + ADDV $128, R5 + ADDV $128, R6 + ADDV $128, R4 + BEQ R7, end + +xor_64_lasx_check: + SGTU $64, R7, R8 + BNE R8, xor_32_lasx_check +xor_64_lasx: + SUBV $64, R7 + XVMOVQ (R5), X0 + XVMOVQ 32(R5), X1 + XVMOVQ (R6), X2 + XVMOVQ 32(R6), X3 + XVXORV X0, X2, X2 + XVXORV X1, X3, X3 + XVMOVQ X2, (R4) + XVMOVQ X3, 32(R4) + ADDV $64, R5 + ADDV $64, R6 + ADDV $64, R4 + BEQ R7, end + +xor_32_lasx_check: + SGTU $32, R7, R8 + BNE R8, xor_16_lasx_check +xor_32_lasx: + SUBV $32, R7 + XVMOVQ (R5), X0 + XVMOVQ (R6), X1 + XVXORV X0, X1, X1 + XVMOVQ X1, (R4) + ADDV $32, R5 + ADDV $32, R6 + ADDV $32, R4 + BEQ R7, end + +xor_16_lasx_check: + SGTU $16, R7, R8 + BNE R8, xor_8_check +xor_16_lasx: + SUBV $16, R7 + VMOVQ (R5), V0 + VMOVQ (R6), V1 + VXORV V0, V1, V1 + VMOVQ V1, (R4) + ADDV $16, R5 + ADDV $16, R6 + ADDV $16, R4 + BEQ R7, end + + SMALL +end: + RET + diff --git a/crypto/internal/fips140/subtle/xor_mips64x.s b/crypto/internal/fips140/subtle/xor_mips64x.s new file mode 100644 index 00000000000..e580235914a --- /dev/null +++ b/crypto/internal/fips140/subtle/xor_mips64x.s @@ -0,0 +1,153 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (mips64 || mips64le) && !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT|NOFRAME, $0 + MOVV dst+0(FP), R1 + MOVV a+8(FP), R2 + MOVV b+16(FP), R3 + MOVV n+24(FP), R4 + +xor_64_check: + SGTU $64, R4, R5 // R5 = 1 if (64 > R4) + BNE R5, xor_32_check +xor_64: + MOVV (R2), R6 + MOVV 8(R2), R7 + MOVV 16(R2), R8 + MOVV 24(R2), R9 + MOVV (R3), R10 + MOVV 8(R3), R11 + MOVV 16(R3), R12 + MOVV 24(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVV R10, (R1) + MOVV R11, 8(R1) + MOVV R12, 16(R1) + MOVV R13, 24(R1) + MOVV 32(R2), R6 + MOVV 40(R2), R7 + MOVV 48(R2), R8 + MOVV 56(R2), R9 + MOVV 32(R3), R10 + MOVV 40(R3), R11 + MOVV 48(R3), R12 + MOVV 56(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVV R10, 32(R1) + MOVV R11, 40(R1) + MOVV R12, 48(R1) + MOVV R13, 56(R1) + ADDV $64, R2 + ADDV $64, R3 + ADDV $64, R1 + SUBV $64, R4 + SGTU $64, R4, R5 + BEQ R0, R5, xor_64 + BEQ R0, R4, end + +xor_32_check: + SGTU $32, R4, R5 + BNE R5, xor_16_check +xor_32: + MOVV (R2), R6 + MOVV 8(R2), R7 + MOVV 16(R2), R8 + MOVV 24(R2), R9 + MOVV (R3), R10 + MOVV 8(R3), R11 + MOVV 16(R3), R12 + MOVV 24(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVV R10, (R1) + MOVV R11, 8(R1) + MOVV R12, 16(R1) + MOVV R13, 24(R1) + ADDV $32, R2 + ADDV $32, R3 + ADDV $32, R1 + SUBV $32, R4 + BEQ R0, R4, end + +xor_16_check: + SGTU $16, R4, R5 + BNE R5, xor_8_check +xor_16: + MOVV (R2), R6 + MOVV 8(R2), R7 + MOVV (R3), R8 + MOVV 8(R3), R9 + XOR R6, R8 + XOR R7, R9 + MOVV R8, (R1) + MOVV R9, 8(R1) + ADDV $16, R2 + ADDV $16, R3 + ADDV $16, R1 + SUBV $16, R4 + BEQ R0, R4, end + +xor_8_check: + SGTU $8, R4, R5 + BNE R5, xor_4_check +xor_8: + MOVV (R2), R6 + MOVV (R3), R7 + XOR R6, R7 + MOVV R7, (R1) + ADDV $8, R1 + ADDV $8, R2 + ADDV $8, R3 + SUBV $8, R4 + BEQ R0, R4, end + +xor_4_check: + SGTU $4, R4, R5 + BNE R5, xor_2_check +xor_4: + MOVW (R2), R6 + MOVW (R3), R7 + XOR R6, R7 + MOVW R7, (R1) + ADDV $4, R2 + ADDV $4, R3 + ADDV $4, R1 + SUBV $4, R4 + BEQ R0, R4, end + +xor_2_check: + SGTU $2, R4, R5 + BNE R5, xor_1 +xor_2: + MOVH (R2), R6 + MOVH (R3), R7 + XOR R6, R7 + MOVH R7, (R1) + ADDV $2, R2 + ADDV $2, R3 + ADDV $2, R1 + SUBV $2, R4 + BEQ R0, R4, end + +xor_1: + MOVB (R2), R6 + MOVB (R3), R7 + XOR R6, R7 + MOVB R7, (R1) + +end: + RET diff --git a/crypto/internal/fips140/subtle/xor_mipsx.s b/crypto/internal/fips140/subtle/xor_mipsx.s new file mode 100644 index 00000000000..1a6b3f409dd --- /dev/null +++ b/crypto/internal/fips140/subtle/xor_mipsx.s @@ -0,0 +1,212 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (mips || mipsle) && !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT|NOFRAME, $0 + MOVW dst+0(FP), R1 + MOVW a+4(FP), R2 + MOVW b+8(FP), R3 + MOVW n+12(FP), R4 + + SGTU $64, R4, R5 // R5 = 1 if (64 > R4) + BNE R5, xor_32_check +xor_64: + MOVW (R2), R6 + MOVW 4(R2), R7 + MOVW 8(R2), R8 + MOVW 12(R2), R9 + MOVW (R3), R10 + MOVW 4(R3), R11 + MOVW 8(R3), R12 + MOVW 12(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, (R1) + MOVW R11, 4(R1) + MOVW R12, 8(R1) + MOVW R13, 12(R1) + MOVW 16(R2), R6 + MOVW 20(R2), R7 + MOVW 24(R2), R8 + MOVW 28(R2), R9 + MOVW 16(R3), R10 + MOVW 20(R3), R11 + MOVW 24(R3), R12 + MOVW 28(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, 16(R1) + MOVW R11, 20(R1) + MOVW R12, 24(R1) + MOVW R13, 28(R1) + MOVW 32(R2), R6 + MOVW 36(R2), R7 + MOVW 40(R2), R8 + MOVW 44(R2), R9 + MOVW 32(R3), R10 + MOVW 36(R3), R11 + MOVW 40(R3), R12 + MOVW 44(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, 32(R1) + MOVW R11, 36(R1) + MOVW R12, 40(R1) + MOVW R13, 44(R1) + MOVW 48(R2), R6 + MOVW 52(R2), R7 + MOVW 56(R2), R8 + MOVW 60(R2), R9 + MOVW 48(R3), R10 + MOVW 52(R3), R11 + MOVW 56(R3), R12 + MOVW 60(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, 48(R1) + MOVW R11, 52(R1) + MOVW R12, 56(R1) + MOVW R13, 60(R1) + ADD $64, R2 + ADD $64, R3 + ADD $64, R1 + SUB $64, R4 + SGTU $64, R4, R5 + BEQ R0, R5, xor_64 + BEQ R0, R4, end + +xor_32_check: + SGTU $32, R4, R5 + BNE R5, xor_16_check +xor_32: + MOVW (R2), R6 + MOVW 4(R2), R7 + MOVW 8(R2), R8 + MOVW 12(R2), R9 + MOVW (R3), R10 + MOVW 4(R3), R11 + MOVW 8(R3), R12 + MOVW 12(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, (R1) + MOVW R11, 4(R1) + MOVW R12, 8(R1) + MOVW R13, 12(R1) + MOVW 16(R2), R6 + MOVW 20(R2), R7 + MOVW 24(R2), R8 + MOVW 28(R2), R9 + MOVW 16(R3), R10 + MOVW 20(R3), R11 + MOVW 24(R3), R12 + MOVW 28(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, 16(R1) + MOVW R11, 20(R1) + MOVW R12, 24(R1) + MOVW R13, 28(R1) + ADD $32, R2 + ADD $32, R3 + ADD $32, R1 + SUB $32, R4 + BEQ R0, R4, end + +xor_16_check: + SGTU $16, R4, R5 + BNE R5, xor_8_check +xor_16: + MOVW (R2), R6 + MOVW 4(R2), R7 + MOVW 8(R2), R8 + MOVW 12(R2), R9 + MOVW (R3), R10 + MOVW 4(R3), R11 + MOVW 8(R3), R12 + MOVW 12(R3), R13 + XOR R6, R10 + XOR R7, R11 + XOR R8, R12 + XOR R9, R13 + MOVW R10, (R1) + MOVW R11, 4(R1) + MOVW R12, 8(R1) + MOVW R13, 12(R1) + ADD $16, R2 + ADD $16, R3 + ADD $16, R1 + SUB $16, R4 + BEQ R0, R4, end + +xor_8_check: + SGTU $8, R4, R5 + BNE R5, xor_4_check +xor_8: + MOVW (R2), R6 + MOVW 4(R2), R7 + MOVW (R3), R8 + MOVW 4(R3), R9 + XOR R6, R8 + XOR R7, R9 + MOVW R8, (R1) + MOVW R9, 4(R1) + ADD $8, R1 + ADD $8, R2 + ADD $8, R3 + SUB $8, R4 + BEQ R0, R4, end + +xor_4_check: + SGTU $4, R4, R5 + BNE R5, xor_2_check +xor_4: + MOVW (R2), R6 + MOVW (R3), R7 + XOR R6, R7 + MOVW R7, (R1) + ADD $4, R2 + ADD $4, R3 + ADD $4, R1 + SUB $4, R4 + BEQ R0, R4, end + +xor_2_check: + SGTU $2, R4, R5 + BNE R5, xor_1 +xor_2: + MOVH (R2), R6 + MOVH (R3), R7 + XOR R6, R7 + MOVH R7, (R1) + ADD $2, R2 + ADD $2, R3 + ADD $2, R1 + SUB $2, R4 + BEQ R0, R4, end + +xor_1: + MOVB (R2), R6 + MOVB (R3), R7 + XOR R6, R7 + MOVB R7, (R1) + +end: + RET diff --git a/crypto/subtle/xor_ppc64x.s b/crypto/internal/fips140/subtle/xor_ppc64x.s similarity index 100% rename from crypto/subtle/xor_ppc64x.s rename to crypto/internal/fips140/subtle/xor_ppc64x.s diff --git a/crypto/internal/fips140/subtle/xor_riscv64.s b/crypto/internal/fips140/subtle/xor_riscv64.s new file mode 100644 index 00000000000..b5fa5dcef45 --- /dev/null +++ b/crypto/internal/fips140/subtle/xor_riscv64.s @@ -0,0 +1,169 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT|NOFRAME, $0 + MOV dst+0(FP), X10 + MOV a+8(FP), X11 + MOV b+16(FP), X12 + MOV n+24(FP), X13 + + MOV $32, X15 + BLT X13, X15, loop4_check + + // Check alignment - if alignment differs we have to do one byte at a time. + AND $7, X10, X5 + AND $7, X11, X6 + AND $7, X12, X7 + BNE X5, X6, loop4_check + BNE X5, X7, loop4_check + BEQZ X5, loop64_check + + // Check one byte at a time until we reach 8 byte alignment. + MOV $8, X8 + SUB X5, X8 + SUB X8, X13 +align: + MOVBU 0(X11), X16 + MOVBU 0(X12), X17 + XOR X16, X17 + MOVB X17, 0(X10) + ADD $1, X10 + ADD $1, X11 + ADD $1, X12 + SUB $1, X8 + BNEZ X8, align + +loop64_check: + MOV $64, X15 + BLT X13, X15, tail32_check + PCALIGN $16 +loop64: + MOV 0(X11), X16 + MOV 0(X12), X17 + MOV 8(X11), X18 + MOV 8(X12), X19 + XOR X16, X17 + XOR X18, X19 + MOV X17, 0(X10) + MOV X19, 8(X10) + MOV 16(X11), X20 + MOV 16(X12), X21 + MOV 24(X11), X22 + MOV 24(X12), X23 + XOR X20, X21 + XOR X22, X23 + MOV X21, 16(X10) + MOV X23, 24(X10) + MOV 32(X11), X16 + MOV 32(X12), X17 + MOV 40(X11), X18 + MOV 40(X12), X19 + XOR X16, X17 + XOR X18, X19 + MOV X17, 32(X10) + MOV X19, 40(X10) + MOV 48(X11), X20 + MOV 48(X12), X21 + MOV 56(X11), X22 + MOV 56(X12), X23 + XOR X20, X21 + XOR X22, X23 + MOV X21, 48(X10) + MOV X23, 56(X10) + ADD $64, X10 + ADD $64, X11 + ADD $64, X12 + SUB $64, X13 + BGE X13, X15, loop64 + BEQZ X13, done + +tail32_check: + MOV $32, X15 + BLT X13, X15, tail16_check + MOV 0(X11), X16 + MOV 0(X12), X17 + MOV 8(X11), X18 + MOV 8(X12), X19 + XOR X16, X17 + XOR X18, X19 + MOV X17, 0(X10) + MOV X19, 8(X10) + MOV 16(X11), X20 + MOV 16(X12), X21 + MOV 24(X11), X22 + MOV 24(X12), X23 + XOR X20, X21 + XOR X22, X23 + MOV X21, 16(X10) + MOV X23, 24(X10) + ADD $32, X10 + ADD $32, X11 + ADD $32, X12 + SUB $32, X13 + BEQZ X13, done + +tail16_check: + MOV $16, X15 + BLT X13, X15, loop4_check + MOV 0(X11), X16 + MOV 0(X12), X17 + MOV 8(X11), X18 + MOV 8(X12), X19 + XOR X16, X17 + XOR X18, X19 + MOV X17, 0(X10) + MOV X19, 8(X10) + ADD $16, X10 + ADD $16, X11 + ADD $16, X12 + SUB $16, X13 + BEQZ X13, done + +loop4_check: + MOV $4, X15 + BLT X13, X15, loop1 + PCALIGN $16 +loop4: + MOVBU 0(X11), X16 + MOVBU 0(X12), X17 + MOVBU 1(X11), X18 + MOVBU 1(X12), X19 + XOR X16, X17 + XOR X18, X19 + MOVB X17, 0(X10) + MOVB X19, 1(X10) + MOVBU 2(X11), X20 + MOVBU 2(X12), X21 + MOVBU 3(X11), X22 + MOVBU 3(X12), X23 + XOR X20, X21 + XOR X22, X23 + MOVB X21, 2(X10) + MOVB X23, 3(X10) + ADD $4, X10 + ADD $4, X11 + ADD $4, X12 + SUB $4, X13 + BGE X13, X15, loop4 + + PCALIGN $16 +loop1: + BEQZ X13, done + MOVBU 0(X11), X16 + MOVBU 0(X12), X17 + XOR X16, X17 + MOVB X17, 0(X10) + ADD $1, X10 + ADD $1, X11 + ADD $1, X12 + SUB $1, X13 + JMP loop1 + +done: + RET diff --git a/crypto/internal/fips140/tls12/cast.go b/crypto/internal/fips140/tls12/cast.go new file mode 100644 index 00000000000..51607175dbe --- /dev/null +++ b/crypto/internal/fips140/tls12/cast.go @@ -0,0 +1,40 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls12 + +import ( + "bytes" + "errors" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" +) + +func init() { + fips140.CAST("TLSv1.2-SHA2-256", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + transcript := []byte{ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + want := []byte{ + 0x8c, 0x3e, 0xed, 0xa7, 0x1c, 0x1b, 0x4c, 0xc0, + 0xa0, 0x44, 0x90, 0x75, 0xa8, 0x8e, 0xbc, 0x7c, + 0x5e, 0x1c, 0x4b, 0x1e, 0x4f, 0xe3, 0xc1, 0x06, + 0xeb, 0xdc, 0xc0, 0x5d, 0xc0, 0xc8, 0xec, 0xf3, + 0xe2, 0xb9, 0xd1, 0x03, 0x5e, 0xb2, 0x60, 0x5d, + 0x12, 0x68, 0x4f, 0x49, 0xdf, 0xa9, 0x9d, 0xcc, + } + if got := MasterSecret(sha256.New, input, transcript); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/tls12/tls12.go b/crypto/internal/fips140/tls12/tls12.go new file mode 100644 index 00000000000..1ceecb691c8 --- /dev/null +++ b/crypto/internal/fips140/tls12/tls12.go @@ -0,0 +1,71 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls12 + +import ( + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" +) + +// PRF implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, +// Section 5 and allowed by SP 800-135, Revision 1, Section 4.2.2. +func PRF[H hash.Hash](hash func() H, secret []byte, label string, seed []byte, keyLen int) []byte { + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + result := make([]byte, keyLen) + pHash(hash, result, secret, labelAndSeed) + return result +} + +// pHash implements the P_hash function, as defined in RFC 5246, Section 5. +func pHash[H hash.Hash](hash func() H, result, secret, seed []byte) { + h := hmac.New(hash, secret) + h.Write(seed) + a := h.Sum(nil) + + for len(result) > 0 { + h.Reset() + h.Write(a) + h.Write(seed) + b := h.Sum(nil) + n := copy(result, b) + result = result[n:] + + h.Reset() + h.Write(a) + a = h.Sum(nil) + } +} + +const masterSecretLength = 48 +const extendedMasterSecretLabel = "extended master secret" + +// MasterSecret implements the TLS 1.2 extended master secret derivation, as +// defined in RFC 7627 and allowed by SP 800-135, Revision 1, Section 4.2.2. +func MasterSecret[H hash.Hash](hash func() H, preMasterSecret, transcript []byte) []byte { + // "The TLS 1.2 KDF is an approved KDF when the following conditions are + // satisfied: [...] (3) P_HASH uses either SHA-256, SHA-384 or SHA-512." + h := hash() + switch any(h).(type) { + case *sha256.Digest: + if h.Size() != 32 { + fips140.RecordNonApproved() + } + case *sha512.Digest: + if h.Size() != 46 && h.Size() != 64 { + fips140.RecordNonApproved() + } + default: + fips140.RecordNonApproved() + } + + return PRF(hash, preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength) +} diff --git a/crypto/internal/fips140/tls13/cast.go b/crypto/internal/fips140/tls13/cast.go new file mode 100644 index 00000000000..b6e924e0b09 --- /dev/null +++ b/crypto/internal/fips140/tls13/cast.go @@ -0,0 +1,39 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls13 + +import ( + "bytes" + "errors" + + _ "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" +) + +func init() { + fips140.CAST("TLSv1.3-SHA2-256", func() error { + input := []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + } + want := []byte{ + 0x78, 0x20, 0x71, 0x75, 0x52, 0xfd, 0x47, 0x67, + 0xe1, 0x07, 0x5c, 0x83, 0x74, 0x2e, 0x49, 0x43, + 0xf7, 0xe3, 0x08, 0x6a, 0x2a, 0xcb, 0x96, 0xc7, + 0xa3, 0x1f, 0xe3, 0x23, 0x56, 0x6e, 0x14, 0x5b, + } + es := NewEarlySecret(sha256.New, nil) + hs := es.HandshakeSecret(nil) + ms := hs.MasterSecret() + transcript := sha256.New() + transcript.Write(input) + if got := ms.ResumptionMasterSecret(transcript); !bytes.Equal(got, want) { + return errors.New("unexpected result") + } + return nil + }) +} diff --git a/crypto/internal/fips140/tls13/tls13.go b/crypto/internal/fips140/tls13/tls13.go new file mode 100644 index 00000000000..1d844838c67 --- /dev/null +++ b/crypto/internal/fips140/tls13/tls13.go @@ -0,0 +1,179 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446, +// Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7. +package tls13 + +import ( + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/hkdf" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" +) + +// We don't set the service indicator in this package but we delegate that to +// the underlying functions because the TLS 1.3 KDF does not have a standard of +// its own. + +// ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. +func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte { + if len("tls13 ")+len(label) > 255 || len(context) > 255 { + // It should be impossible for this to panic: labels are fixed strings, + // and context is either a fixed-length computed hash, or parsed from a + // field which has the same length limitation. + // + // Another reasonable approach might be to return a randomized slice if + // we encounter an error, which would break the connection, but avoid + // panicking. This would perhaps be safer but significantly more + // confusing to users. + panic("tls13: label or context too long") + } + hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context)) + hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length)) + hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label))) + hkdfLabel = append(hkdfLabel, "tls13 "...) + hkdfLabel = append(hkdfLabel, label...) + hkdfLabel = append(hkdfLabel, byte(len(context))) + hkdfLabel = append(hkdfLabel, context...) + return hkdf.Expand(hash, secret, string(hkdfLabel), length) +} + +func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte { + if newSecret == nil { + newSecret = make([]byte, hash().Size()) + } + return hkdf.Extract(hash, newSecret, currentSecret) +} + +func deriveSecret[H hash.Hash](hash func() H, secret []byte, label string, transcript hash.Hash) []byte { + if transcript == nil { + transcript = hash() + } + return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size()) +} + +const ( + resumptionBinderLabel = "res binder" + clientEarlyTrafficLabel = "c e traffic" + clientHandshakeTrafficLabel = "c hs traffic" + serverHandshakeTrafficLabel = "s hs traffic" + clientApplicationTrafficLabel = "c ap traffic" + serverApplicationTrafficLabel = "s ap traffic" + earlyExporterLabel = "e exp master" + exporterLabel = "exp master" + resumptionLabel = "res master" +) + +type EarlySecret struct { + secret []byte + hash func() hash.Hash +} + +func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret { + return &EarlySecret{ + secret: extract(h, psk, nil), + hash: func() hash.Hash { return h() }, + } +} + +func (s *EarlySecret) ResumptionBinderKey() []byte { + return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil) +} + +// ClientEarlyTrafficSecret derives the client_early_traffic_secret from the +// early secret and the transcript up to the ClientHello. +func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript) +} + +type HandshakeSecret struct { + secret []byte + hash func() hash.Hash +} + +func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret { + derived := deriveSecret(s.hash, s.secret, "derived", nil) + return &HandshakeSecret{ + secret: extract(s.hash, sharedSecret, derived), + hash: s.hash, + } +} + +// ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from +// the handshake secret and the transcript up to the ServerHello. +func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript) +} + +// ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from +// the handshake secret and the transcript up to the ServerHello. +func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript) +} + +type MasterSecret struct { + secret []byte + hash func() hash.Hash +} + +func (s *HandshakeSecret) MasterSecret() *MasterSecret { + derived := deriveSecret(s.hash, s.secret, "derived", nil) + return &MasterSecret{ + secret: extract(s.hash, nil, derived), + hash: s.hash, + } +} + +// ClientApplicationTrafficSecret derives the client_application_traffic_secret_0 +// from the master secret and the transcript up to the server Finished. +func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript) +} + +// ServerApplicationTrafficSecret derives the server_application_traffic_secret_0 +// from the master secret and the transcript up to the server Finished. +func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript) +} + +// ResumptionMasterSecret derives the resumption_master_secret from the master secret +// and the transcript up to the client Finished. +func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte { + return deriveSecret(s.hash, s.secret, resumptionLabel, transcript) +} + +type ExporterMasterSecret struct { + secret []byte + hash func() hash.Hash +} + +// ExporterMasterSecret derives the exporter_master_secret from the master secret +// and the transcript up to the server Finished. +func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { + return &ExporterMasterSecret{ + secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript), + hash: s.hash, + } +} + +// EarlyExporterMasterSecret derives the exporter_master_secret from the early secret +// and the transcript up to the ClientHello. +func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { + return &ExporterMasterSecret{ + secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript), + hash: s.hash, + } +} + +func (s *ExporterMasterSecret) Exporter(label string, context []byte, length int) []byte { + secret := deriveSecret(s.hash, s.secret, label, nil) + h := s.hash() + h.Write(context) + return ExpandLabel(s.hash, secret, "exporter", h.Sum(nil), length) +} + +func TestingOnlyExporterSecret(s *ExporterMasterSecret) []byte { + return s.secret +} diff --git a/crypto/internal/fips140deps/byteorder/byteorder.go b/crypto/internal/fips140deps/byteorder/byteorder.go new file mode 100644 index 00000000000..188e81d6776 --- /dev/null +++ b/crypto/internal/fips140deps/byteorder/byteorder.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package byteorder + +import ( + "github.com/runZeroInc/excrypto/internal/byteorder" +) + +func LEUint16(b []byte) uint16 { + return byteorder.LEUint16(b) +} + +func BEUint32(b []byte) uint32 { + return byteorder.BEUint32(b) +} + +func BEUint64(b []byte) uint64 { + return byteorder.BEUint64(b) +} + +func LEUint64(b []byte) uint64 { + return byteorder.LEUint64(b) +} + +func BEPutUint16(b []byte, v uint16) { + byteorder.BEPutUint16(b, v) +} + +func BEPutUint32(b []byte, v uint32) { + byteorder.BEPutUint32(b, v) +} + +func BEPutUint64(b []byte, v uint64) { + byteorder.BEPutUint64(b, v) +} + +func LEPutUint64(b []byte, v uint64) { + byteorder.LEPutUint64(b, v) +} + +func BEAppendUint16(b []byte, v uint16) []byte { + return byteorder.BEAppendUint16(b, v) +} + +func BEAppendUint32(b []byte, v uint32) []byte { + return byteorder.BEAppendUint32(b, v) +} + +func BEAppendUint64(b []byte, v uint64) []byte { + return byteorder.BEAppendUint64(b, v) +} diff --git a/crypto/internal/fips140deps/cpu/cpu.go b/crypto/internal/fips140deps/cpu/cpu.go new file mode 100644 index 00000000000..27acf62ee42 --- /dev/null +++ b/crypto/internal/fips140deps/cpu/cpu.go @@ -0,0 +1,49 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "github.com/runZeroInc/excrypto/internal/cpu" + "github.com/runZeroInc/excrypto/internal/goarch" +) + +const ( + BigEndian = goarch.BigEndian + AMD64 = goarch.IsAmd64 == 1 + ARM64 = goarch.IsArm64 == 1 + PPC64 = goarch.IsPpc64 == 1 + PPC64le = goarch.IsPpc64le == 1 +) + +var ( + ARM64HasAES = cpu.ARM64.HasAES + ARM64HasPMULL = cpu.ARM64.HasPMULL + ARM64HasSHA2 = cpu.ARM64.HasSHA2 + ARM64HasSHA512 = cpu.ARM64.HasSHA512 + ARM64HasSHA3 = cpu.ARM64.HasSHA3 + + LOONG64HasLSX = cpu.Loong64.HasLSX + LOONG64HasLASX = cpu.Loong64.HasLASX + + S390XHasAES = cpu.S390X.HasAES + S390XHasAESCBC = cpu.S390X.HasAESCBC + S390XHasAESCTR = cpu.S390X.HasAESCTR + S390XHasAESGCM = cpu.S390X.HasAESGCM + S390XHasECDSA = cpu.S390X.HasECDSA + S390XHasGHASH = cpu.S390X.HasGHASH + S390XHasSHA256 = cpu.S390X.HasSHA256 + S390XHasSHA3 = cpu.S390X.HasSHA3 + S390XHasSHA512 = cpu.S390X.HasSHA512 + + X86HasAES = cpu.X86.HasAES + X86HasADX = cpu.X86.HasADX + X86HasAVX = cpu.X86.HasAVX + X86HasAVX2 = cpu.X86.HasAVX2 + X86HasBMI2 = cpu.X86.HasBMI2 + X86HasPCLMULQDQ = cpu.X86.HasPCLMULQDQ + X86HasSHA = cpu.X86.HasSHA + X86HasSSE41 = cpu.X86.HasSSE41 + X86HasSSSE3 = cpu.X86.HasSSSE3 +) diff --git a/crypto/internal/fips140deps/fipsdeps.go b/crypto/internal/fips140deps/fipsdeps.go new file mode 100644 index 00000000000..307144339f4 --- /dev/null +++ b/crypto/internal/fips140deps/fipsdeps.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fipsdeps contains wrapper packages for internal APIs that are exposed +// to the FIPS module. Since modules are frozen upon validation and supported +// for a number of future versions, APIs exposed by crypto/internal/fips140deps/... +// must not be changed until the modules that use them are no longer supported. +package fipsdeps diff --git a/crypto/internal/fips140deps/fipsdeps_test.go b/crypto/internal/fips140deps/fipsdeps_test.go new file mode 100644 index 00000000000..9e30c755cdf --- /dev/null +++ b/crypto/internal/fips140deps/fipsdeps_test.go @@ -0,0 +1,111 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fipsdeps + +import ( + "strings" + "testing" + + "github.com/runZeroInc/excrypto/internal/testenv" +) + +// AllowedInternalPackages are internal packages that can be imported from the +// FIPS module. The API of these packages ends up locked for the lifetime of the +// validated module, which can be years. +// +// DO NOT add new packages here just to make the tests pass. +var AllowedInternalPackages = map[string]bool{ + // entropy.Depleted is the external passive entropy source, and sysrand.Read + // is the actual (but uncredited!) random bytes source. + "github.com/runZeroInc/excrypto/crypto/internal/entropy": true, + "github.com/runZeroInc/excrypto/crypto/internal/sysrand": true, + + // impl.Register is how the packages expose their alternative + // implementations to tests outside the module. + "github.com/runZeroInc/excrypto/crypto/internal/impl": true, + + // randutil.MaybeReadByte is used in non-FIPS mode by GenerateKey functions. + "github.com/runZeroInc/excrypto/crypto/internal/randutil": true, +} + +func TestImports(t *testing.T) { + cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{$path := .ImportPath -}} +{{range .Imports -}} +{{$path}} {{.}} +{{end -}} +{{range .TestImports -}} +{{$path}} {{.}} +{{end -}} +{{range .XTestImports -}} +{{$path}} {{.}} +{{end -}}`, "github.com/runZeroInc/excrypto/crypto/internal/fips140/...") + bout, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("go list: %v\n%s", err, bout) + } + out := string(bout) + + // In a snapshot, all the paths are crypto/internal/fips140/v1.2.3/... + // Determine the version number and remove it for the test. + _, v, _ := strings.Cut(out, "github.com/runZeroInc/excrypto/crypto/internal/fips140/") + v, _, _ = strings.Cut(v, "/") + v, _, _ = strings.Cut(v, " ") + if strings.HasPrefix(v, "v") && strings.Count(v, ".") == 2 { + out = strings.ReplaceAll(out, "github.com/runZeroInc/excrypto/crypto/internal/fips140/"+v, "github.com/runZeroInc/excrypto/crypto/internal/fips140") + } + + allPackages := make(map[string]bool) + + // importCheck is the set of packages that import crypto/internal/fips140/check. + importCheck := make(map[string]bool) + + for _, line := range strings.Split(out, "\n") { + if line == "" { + continue + } + pkg, importedPkg, _ := strings.Cut(line, " ") + + allPackages[pkg] = true + + if importedPkg == "github.com/runZeroInc/excrypto/crypto/internal/fips140/check" { + importCheck[pkg] = true + } + + // Ensure we don't import any unexpected internal package from the FIPS + // module, since we can't change the module source after it starts + // validation. This locks in the API of otherwise internal packages. + if importedPkg == "github.com/runZeroInc/excrypto/crypto/internal/fips140" || + strings.HasPrefix(importedPkg, "github.com/runZeroInc/excrypto/crypto/internal/fips140/") || + strings.HasPrefix(importedPkg, "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/") { + continue + } + if AllowedInternalPackages[importedPkg] { + continue + } + if strings.Contains(importedPkg, "internal") { + t.Errorf("unexpected import of internal package: %s -> %s", pkg, importedPkg) + } + } + + // Ensure that all packages except check and check's dependencies import check. + for pkg := range allPackages { + switch pkg { + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/check": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/alias": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/hmac": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256": + case "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512": + default: + if !importCheck[pkg] { + t.Errorf("package %s does not import github.com/runZeroInc/excrypto/crypto/internal/fips140/check", pkg) + } + } + } +} diff --git a/crypto/internal/fips140deps/godebug/godebug.go b/crypto/internal/fips140deps/godebug/godebug.go new file mode 100644 index 00000000000..6e002f2c8b1 --- /dev/null +++ b/crypto/internal/fips140deps/godebug/godebug.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package godebug + +import "github.com/runZeroInc/excrypto/internal/godebug" + +type Setting godebug.Setting + +func New(name string) *Setting { + return (*Setting)(godebug.New(name)) +} + +func (s *Setting) Value() string { + return (*godebug.Setting)(s).Value() +} + +func Value(name string) string { + return godebug.New(name).Value() +} diff --git a/crypto/internal/fips140hash/hash.go b/crypto/internal/fips140hash/hash.go new file mode 100644 index 00000000000..d829eb4df22 --- /dev/null +++ b/crypto/internal/fips140hash/hash.go @@ -0,0 +1,36 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140hash + +import ( + _ "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + fsha3 "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/sha3" +) + +//go:linkname sha3Unwrap +func sha3Unwrap(*sha3.SHA3) *fsha3.Digest + +// Unwrap returns h, or a crypto/internal/fips140 inner implementation of h. +// +// The return value can be type asserted to one of +// [crypto/internal/fips140/sha256.Digest], +// [crypto/internal/fips140/sha512.Digest], or +// [crypto/internal/fips140/sha3.Digest] if it is a FIPS 140-3 approved hash. +func Unwrap(h hash.Hash) hash.Hash { + if sha3, ok := h.(*sha3.SHA3); ok { + return sha3Unwrap(sha3) + } + return h +} + +// UnwrapNew returns a function that calls newHash and applies [Unwrap] to the +// return value. +func UnwrapNew[Hash hash.Hash](newHash func() Hash) func() hash.Hash { + return func() hash.Hash { return Unwrap(newHash()) } +} diff --git a/crypto/internal/fips140only/fips140only.go b/crypto/internal/fips140only/fips140only.go new file mode 100644 index 00000000000..bae6f19b500 --- /dev/null +++ b/crypto/internal/fips140only/fips140only.go @@ -0,0 +1,36 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fips140only + +import ( + "io" + _ "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/godebug" +) + +// Enabled reports whether FIPS 140-only mode is enabled, in which non-approved +// cryptography returns an error or panics. +var Enabled = godebug.New("fips140").Value() == "only" + +func ApprovedHash(h hash.Hash) bool { + switch h.(type) { + case *sha256.Digest, *sha512.Digest, *sha3.Digest: + return true + default: + return false + } +} + +func ApprovedRandomReader(r io.Reader) bool { + _, ok := r.(drbg.DefaultReader) + return ok +} diff --git a/crypto/internal/hpke/hpke.go b/crypto/internal/hpke/hpke.go index a1453171025..755af8dc7ff 100644 --- a/crypto/internal/hpke/hpke.go +++ b/crypto/internal/hpke/hpke.go @@ -5,19 +5,17 @@ package hpke import ( - "encoding/binary" + "crypto/rand" "errors" "math/bits" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/ecdh" - + "github.com/runZeroInc/excrypto/crypto/hkdf" + "github.com/runZeroInc/excrypto/internal/byteorder" "github.com/runZeroInc/excrypto/x/crypto/chacha20poly1305" - "github.com/runZeroInc/excrypto/x/crypto/hkdf" ) // testingOnlyGenerateKey is only used during testing, to provide @@ -28,28 +26,23 @@ type hkdfKDF struct { hash crypto.Hash } -func (kdf *hkdfKDF) LabeledExtract(suiteID []byte, salt []byte, label string, inputKey []byte) []byte { - labeledIKM := make([]byte, 0, 7+len(suiteID)+len(label)+len(inputKey)) +func (kdf *hkdfKDF) LabeledExtract(sid []byte, salt []byte, label string, inputKey []byte) ([]byte, error) { + labeledIKM := make([]byte, 0, 7+len(sid)+len(label)+len(inputKey)) labeledIKM = append(labeledIKM, []byte("HPKE-v1")...) - labeledIKM = append(labeledIKM, suiteID...) + labeledIKM = append(labeledIKM, sid...) labeledIKM = append(labeledIKM, label...) labeledIKM = append(labeledIKM, inputKey...) return hkdf.Extract(kdf.hash.New, labeledIKM, salt) } -func (kdf *hkdfKDF) LabeledExpand(suiteID []byte, randomKey []byte, label string, info []byte, length uint16) []byte { +func (kdf *hkdfKDF) LabeledExpand(suiteID []byte, randomKey []byte, label string, info []byte, length uint16) ([]byte, error) { labeledInfo := make([]byte, 0, 2+7+len(suiteID)+len(label)+len(info)) - labeledInfo = binary.BigEndian.AppendUint16(labeledInfo, length) + labeledInfo = byteorder.BEAppendUint16(labeledInfo, length) labeledInfo = append(labeledInfo, []byte("HPKE-v1")...) labeledInfo = append(labeledInfo, suiteID...) labeledInfo = append(labeledInfo, label...) labeledInfo = append(labeledInfo, info...) - out := make([]byte, length) - n, err := hkdf.Expand(kdf.hash.New, randomKey, labeledInfo).Read(out) - if err != nil || n != int(length) { - panic("hpke: LabeledExpand failed unexpectedly") - } - return out + return hkdf.Expand(kdf.hash.New, randomKey, string(labeledInfo), int(length)) } // dhKEM implements the KEM specified in RFC 9180, Section 4.1. @@ -61,13 +54,17 @@ type dhKEM struct { nSecret uint16 } +type KemID uint16 + +const DHKEM_X25519_HKDF_SHA256 = 0x0020 + var SupportedKEMs = map[uint16]struct { curve ecdh.Curve hash crypto.Hash nSecret uint16 }{ // RFC 9180 Section 7.1 - 0x0020: {ecdh.X25519(), crypto.SHA256, 32}, + DHKEM_X25519_HKDF_SHA256: {ecdh.X25519(), crypto.SHA256, 32}, } func newDHKem(kemID uint16) (*dhKEM, error) { @@ -78,13 +75,16 @@ func newDHKem(kemID uint16) (*dhKEM, error) { return &dhKEM{ dh: suite.curve, kdf: hkdfKDF{suite.hash}, - suiteID: binary.BigEndian.AppendUint16([]byte("KEM"), kemID), + suiteID: byteorder.BEAppendUint16([]byte("KEM"), kemID), nSecret: suite.nSecret, }, nil } -func (dh *dhKEM) ExtractAndExpand(dhKey, kemContext []byte) []byte { - eaePRK := dh.kdf.LabeledExtract(dh.suiteID[:], nil, "eae_prk", dhKey) +func (dh *dhKEM) ExtractAndExpand(dhKey, kemContext []byte) ([]byte, error) { + eaePRK, err := dh.kdf.LabeledExtract(dh.suiteID[:], nil, "eae_prk", dhKey) + if err != nil { + return nil, err + } return dh.kdf.LabeledExpand(dh.suiteID[:], eaePRK, "shared_secret", kemContext, dh.nSecret) } @@ -106,13 +106,28 @@ func (dh *dhKEM) Encap(pubRecipient *ecdh.PublicKey) (sharedSecret []byte, encap encPubRecip := pubRecipient.Bytes() kemContext := append(encPubEph, encPubRecip...) + sharedSecret, err = dh.ExtractAndExpand(dhVal, kemContext) + if err != nil { + return nil, nil, err + } + return sharedSecret, encPubEph, nil +} - return dh.ExtractAndExpand(dhVal, kemContext), encPubEph, nil +func (dh *dhKEM) Decap(encPubEph []byte, secRecipient *ecdh.PrivateKey) ([]byte, error) { + pubEph, err := dh.dh.NewPublicKey(encPubEph) + if err != nil { + return nil, err + } + dhVal, err := secRecipient.ECDH(pubEph) + if err != nil { + return nil, err + } + kemContext := append(encPubEph, secRecipient.PublicKey().Bytes()...) + return dh.ExtractAndExpand(dhVal, kemContext) } -type Sender struct { +type context struct { aead cipher.AEAD - kem *dhKEM sharedSecret []byte @@ -125,6 +140,14 @@ type Sender struct { seqNum uint128 } +type Sender struct { + *context +} + +type Recipient struct { + *context +} + var aesGCMNew = func(key []byte) (cipher.AEAD, error) { block, err := aes.NewCipher(key) if err != nil { @@ -133,102 +156,165 @@ var aesGCMNew = func(key []byte) (cipher.AEAD, error) { return cipher.NewGCM(block) } +type AEADID uint16 + +const ( + AEAD_AES_128_GCM = 0x0001 + AEAD_AES_256_GCM = 0x0002 + AEAD_ChaCha20Poly1305 = 0x0003 +) + var SupportedAEADs = map[uint16]struct { keySize int nonceSize int aead func([]byte) (cipher.AEAD, error) }{ // RFC 9180, Section 7.3 - 0x0001: {keySize: 16, nonceSize: 12, aead: aesGCMNew}, - 0x0002: {keySize: 32, nonceSize: 12, aead: aesGCMNew}, - 0x0003: {keySize: chacha20poly1305.KeySize, nonceSize: chacha20poly1305.NonceSize, aead: chacha20poly1305.New}, + AEAD_AES_128_GCM: {keySize: 16, nonceSize: 12, aead: aesGCMNew}, + AEAD_AES_256_GCM: {keySize: 32, nonceSize: 12, aead: aesGCMNew}, + AEAD_ChaCha20Poly1305: {keySize: chacha20poly1305.KeySize, nonceSize: chacha20poly1305.NonceSize, aead: chacha20poly1305.New}, } +type KDFID uint16 + +const KDF_HKDF_SHA256 = 0x0001 + var SupportedKDFs = map[uint16]func() *hkdfKDF{ // RFC 9180, Section 7.2 - 0x0001: func() *hkdfKDF { return &hkdfKDF{crypto.SHA256} }, + KDF_HKDF_SHA256: func() *hkdfKDF { return &hkdfKDF{crypto.SHA256} }, } -func SetupSender(kemID, kdfID, aeadID uint16, pub crypto.PublicKey, info []byte) ([]byte, *Sender, error) { - suiteID := SuiteID(kemID, kdfID, aeadID) - - kem, err := newDHKem(kemID) - if err != nil { - return nil, nil, err - } - pubRecipient, ok := pub.(*ecdh.PublicKey) - if !ok { - return nil, nil, errors.New("incorrect public key type") - } - sharedSecret, encapsulatedKey, err := kem.Encap(pubRecipient) - if err != nil { - return nil, nil, err - } +func newContext(sharedSecret []byte, kemID, kdfID, aeadID uint16, info []byte) (*context, error) { + sid := suiteID(kemID, kdfID, aeadID) kdfInit, ok := SupportedKDFs[kdfID] if !ok { - return nil, nil, errors.New("unsupported KDF id") + return nil, errors.New("unsupported KDF id") } kdf := kdfInit() aeadInfo, ok := SupportedAEADs[aeadID] if !ok { - return nil, nil, errors.New("unsupported AEAD id") + return nil, errors.New("unsupported AEAD id") } - pskIDHash := kdf.LabeledExtract(suiteID, nil, "psk_id_hash", nil) - infoHash := kdf.LabeledExtract(suiteID, nil, "info_hash", info) + pskIDHash, err := kdf.LabeledExtract(sid, nil, "psk_id_hash", nil) + if err != nil { + return nil, err + } + infoHash, err := kdf.LabeledExtract(sid, nil, "info_hash", info) + if err != nil { + return nil, err + } ksContext := append([]byte{0}, pskIDHash...) ksContext = append(ksContext, infoHash...) - secret := kdf.LabeledExtract(suiteID, sharedSecret, "secret", nil) - - key := kdf.LabeledExpand(suiteID, secret, "key", ksContext, uint16(aeadInfo.keySize) /* Nk - key size for AEAD */) - baseNonce := kdf.LabeledExpand(suiteID, secret, "base_nonce", ksContext, uint16(aeadInfo.nonceSize) /* Nn - nonce size for AEAD */) - exporterSecret := kdf.LabeledExpand(suiteID, secret, "exp", ksContext, uint16(kdf.hash.Size()) /* Nh - hash output size of the kdf*/) + secret, err := kdf.LabeledExtract(sid, sharedSecret, "secret", nil) + if err != nil { + return nil, err + } + key, err := kdf.LabeledExpand(sid, secret, "key", ksContext, uint16(aeadInfo.keySize) /* Nk - key size for AEAD */) + if err != nil { + return nil, err + } + baseNonce, err := kdf.LabeledExpand(sid, secret, "base_nonce", ksContext, uint16(aeadInfo.nonceSize) /* Nn - nonce size for AEAD */) + if err != nil { + return nil, err + } + exporterSecret, err := kdf.LabeledExpand(sid, secret, "exp", ksContext, uint16(kdf.hash.Size()) /* Nh - hash output size of the kdf*/) + if err != nil { + return nil, err + } aead, err := aeadInfo.aead(key) if err != nil { - return nil, nil, err + return nil, err } - return encapsulatedKey, &Sender{ - kem: kem, + return &context{ aead: aead, sharedSecret: sharedSecret, - suiteID: suiteID, + suiteID: sid, key: key, baseNonce: baseNonce, exporterSecret: exporterSecret, }, nil } -func (s *Sender) nextNonce() []byte { - nonce := s.seqNum.bytes()[16-s.aead.NonceSize():] - for i := range s.baseNonce { - nonce[i] ^= s.baseNonce[i] +func SetupSender(kemID, kdfID, aeadID uint16, pub *ecdh.PublicKey, info []byte) ([]byte, *Sender, error) { + kem, err := newDHKem(kemID) + if err != nil { + return nil, nil, err } + sharedSecret, encapsulatedKey, err := kem.Encap(pub) + if err != nil { + return nil, nil, err + } + + context, err := newContext(sharedSecret, kemID, kdfID, aeadID, info) + if err != nil { + return nil, nil, err + } + + return encapsulatedKey, &Sender{context}, nil +} + +func SetupRecipient(kemID, kdfID, aeadID uint16, priv *ecdh.PrivateKey, info, encPubEph []byte) (*Recipient, error) { + kem, err := newDHKem(kemID) + if err != nil { + return nil, err + } + sharedSecret, err := kem.Decap(encPubEph, priv) + if err != nil { + return nil, err + } + + context, err := newContext(sharedSecret, kemID, kdfID, aeadID, info) + if err != nil { + return nil, err + } + + return &Recipient{context}, nil +} + +func (ctx *context) nextNonce() []byte { + nonce := ctx.seqNum.bytes()[16-ctx.aead.NonceSize():] + for i := range ctx.baseNonce { + nonce[i] ^= ctx.baseNonce[i] + } + return nonce +} + +func (ctx *context) incrementNonce() { // Message limit is, according to the RFC, 2^95+1, which // is somewhat confusing, but we do as we're told. - if s.seqNum.bitLen() >= (s.aead.NonceSize()*8)-1 { + if ctx.seqNum.bitLen() >= (ctx.aead.NonceSize()*8)-1 { panic("message limit reached") } - s.seqNum = s.seqNum.addOne() - return nonce + ctx.seqNum = ctx.seqNum.addOne() } func (s *Sender) Seal(aad, plaintext []byte) ([]byte, error) { - ciphertext := s.aead.Seal(nil, s.nextNonce(), plaintext, aad) + s.incrementNonce() return ciphertext, nil } -func SuiteID(kemID, kdfID, aeadID uint16) []byte { +func (r *Recipient) Open(aad, ciphertext []byte) ([]byte, error) { + plaintext, err := r.aead.Open(nil, r.nextNonce(), ciphertext, aad) + if err != nil { + return nil, err + } + r.incrementNonce() + return plaintext, nil +} + +func suiteID(kemID, kdfID, aeadID uint16) []byte { suiteID := make([]byte, 0, 4+2+2+2) suiteID = append(suiteID, []byte("HPKE")...) - suiteID = binary.BigEndian.AppendUint16(suiteID, kemID) - suiteID = binary.BigEndian.AppendUint16(suiteID, kdfID) - suiteID = binary.BigEndian.AppendUint16(suiteID, aeadID) + suiteID = byteorder.BEAppendUint16(suiteID, kemID) + suiteID = byteorder.BEAppendUint16(suiteID, kdfID) + suiteID = byteorder.BEAppendUint16(suiteID, aeadID) return suiteID } @@ -240,6 +326,14 @@ func ParseHPKEPublicKey(kemID uint16, bytes []byte) (*ecdh.PublicKey, error) { return kemInfo.curve.NewPublicKey(bytes) } +func ParseHPKEPrivateKey(kemID uint16, bytes []byte) (*ecdh.PrivateKey, error) { + kemInfo, ok := SupportedKEMs[kemID] + if !ok { + return nil, errors.New("unsupported KEM id") + } + return kemInfo.curve.NewPrivateKey(bytes) +} + type uint128 struct { hi, lo uint64 } @@ -255,7 +349,7 @@ func (u uint128) bitLen() int { func (u uint128) bytes() []byte { b := make([]byte, 16) - binary.BigEndian.PutUint64(b[0:], u.hi) - binary.BigEndian.PutUint64(b[8:], u.lo) + byteorder.BEPutUint64(b[0:], u.hi) + byteorder.BEPutUint64(b[8:], u.lo) return b } diff --git a/crypto/internal/hpke/hpke_test.go b/crypto/internal/hpke/hpke_test.go index 91952b52372..ff54ec1c8f3 100644 --- a/crypto/internal/hpke/hpke_test.go +++ b/crypto/internal/hpke/hpke_test.go @@ -104,7 +104,7 @@ func TestRFC9180Vectors(t *testing.T) { } t.Cleanup(func() { testingOnlyGenerateKey = nil }) - encap, context, err := SetupSender( + encap, sender, err := SetupSender( uint16(kemID), uint16(kdfID), uint16(aeadID), @@ -119,21 +119,42 @@ func TestRFC9180Vectors(t *testing.T) { if !bytes.Equal(encap, expectedEncap) { t.Errorf("unexpected encapsulated key, got: %x, want %x", encap, expectedEncap) } - expectedSharedSecret := mustDecodeHex(t, setup["shared_secret"]) - if !bytes.Equal(context.sharedSecret, expectedSharedSecret) { - t.Errorf("unexpected shared secret, got: %x, want %x", context.sharedSecret, expectedSharedSecret) - } - expectedKey := mustDecodeHex(t, setup["key"]) - if !bytes.Equal(context.key, expectedKey) { - t.Errorf("unexpected key, got: %x, want %x", context.key, expectedKey) + + privKeyBytes := mustDecodeHex(t, setup["skRm"]) + priv, err := ParseHPKEPrivateKey(uint16(kemID), privKeyBytes) + if err != nil { + t.Fatal(err) } - expectedBaseNonce := mustDecodeHex(t, setup["base_nonce"]) - if !bytes.Equal(context.baseNonce, expectedBaseNonce) { - t.Errorf("unexpected base nonce, got: %x, want %x", context.baseNonce, expectedBaseNonce) + + recipient, err := SetupRecipient( + uint16(kemID), + uint16(kdfID), + uint16(aeadID), + priv, + info, + encap, + ) + if err != nil { + t.Fatal(err) } - expectedExporterSecret := mustDecodeHex(t, setup["exporter_secret"]) - if !bytes.Equal(context.exporterSecret, expectedExporterSecret) { - t.Errorf("unexpected exporter secret, got: %x, want %x", context.exporterSecret, expectedExporterSecret) + + for _, ctx := range []*context{sender.context, recipient.context} { + expectedSharedSecret := mustDecodeHex(t, setup["shared_secret"]) + if !bytes.Equal(ctx.sharedSecret, expectedSharedSecret) { + t.Errorf("unexpected shared secret, got: %x, want %x", ctx.sharedSecret, expectedSharedSecret) + } + expectedKey := mustDecodeHex(t, setup["key"]) + if !bytes.Equal(ctx.key, expectedKey) { + t.Errorf("unexpected key, got: %x, want %x", ctx.key, expectedKey) + } + expectedBaseNonce := mustDecodeHex(t, setup["base_nonce"]) + if !bytes.Equal(ctx.baseNonce, expectedBaseNonce) { + t.Errorf("unexpected base nonce, got: %x, want %x", ctx.baseNonce, expectedBaseNonce) + } + expectedExporterSecret := mustDecodeHex(t, setup["exporter_secret"]) + if !bytes.Equal(ctx.exporterSecret, expectedExporterSecret) { + t.Errorf("unexpected exporter secret, got: %x, want %x", ctx.exporterSecret, expectedExporterSecret) + } } for _, enc := range parseVectorEncryptions(vector.Encryptions) { @@ -142,26 +163,31 @@ func TestRFC9180Vectors(t *testing.T) { if err != nil { t.Fatal(err) } - context.seqNum = uint128{lo: uint64(seqNum)} + sender.seqNum = uint128{lo: uint64(seqNum)} + recipient.seqNum = uint128{lo: uint64(seqNum)} expectedNonce := mustDecodeHex(t, enc["nonce"]) - // We can't call nextNonce, because it increments the sequence number, - // so just compute it directly. - computedNonce := context.seqNum.bytes()[16-context.aead.NonceSize():] - for i := range context.baseNonce { - computedNonce[i] ^= context.baseNonce[i] - } + computedNonce := sender.nextNonce() if !bytes.Equal(computedNonce, expectedNonce) { t.Errorf("unexpected nonce: got %x, want %x", computedNonce, expectedNonce) } expectedCiphertext := mustDecodeHex(t, enc["ct"]) - ciphertext, err := context.Seal(mustDecodeHex(t, enc["aad"]), mustDecodeHex(t, enc["pt"])) + ciphertext, err := sender.Seal(mustDecodeHex(t, enc["aad"]), mustDecodeHex(t, enc["pt"])) if err != nil { t.Fatal(err) } if !bytes.Equal(ciphertext, expectedCiphertext) { t.Errorf("unexpected ciphertext: got %x want %x", ciphertext, expectedCiphertext) } + + expectedPlaintext := mustDecodeHex(t, enc["pt"]) + plaintext, err := recipient.Open(mustDecodeHex(t, enc["aad"]), mustDecodeHex(t, enc["ct"])) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(plaintext, expectedPlaintext) { + t.Errorf("unexpected plaintext: got %x want %x", plaintext, expectedPlaintext) + } }) } }) diff --git a/crypto/internal/impl/impl.go b/crypto/internal/impl/impl.go new file mode 100644 index 00000000000..193839f1f19 --- /dev/null +++ b/crypto/internal/impl/impl.go @@ -0,0 +1,107 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package impl is a registry of alternative implementations of cryptographic +// primitives, to allow selecting them for testing. +package impl + +import "strings" + +type implementation struct { + Package string + Name string + Available bool + Toggle *bool +} + +var allImplementations []implementation + +// Register records an alternative implementation of a cryptographic primitive. +// The implementation might be available or not based on CPU support. If +// available is false, the implementation is unavailable and can't be tested on +// this machine. If available is true, it can be set to false to disable the +// implementation. If all alternative implementations but one are disabled, the +// remaining one must be used (i.e. disabling one implementation must not +// implicitly disable any other). Each package has an implicit base +// implementation that is selected when all alternatives are unavailable or +// disabled. pkg must be the package name, not path (e.g. "aes" not "crypto/aes"). +func Register(pkg, name string, available *bool) { + if strings.Contains(pkg, "/") { + panic("impl: package name must not contain slashes") + } + allImplementations = append(allImplementations, implementation{ + Package: pkg, + Name: name, + Available: *available, + Toggle: available, + }) +} + +// Packages returns the list of all packages for which alternative +// implementations are registered. +func Packages() []string { + var pkgs []string + seen := make(map[string]bool) + for _, i := range allImplementations { + if !seen[i.Package] { + pkgs = append(pkgs, i.Package) + seen[i.Package] = true + } + } + return pkgs +} + +// List returns the names of all alternative implementations registered for the +// given package, whether available or not. The implicit base implementation is +// not included. +func List(pkg string) []string { + var names []string + for _, i := range allImplementations { + if i.Package == pkg { + names = append(names, i.Name) + } + } + return names +} + +func available(pkg, name string) bool { + for _, i := range allImplementations { + if i.Package == pkg && i.Name == name { + return i.Available + } + } + panic("unknown implementation") +} + +// Select disables all implementations for the given package except the one +// with the given name. If name is empty, the base implementation is selected. +// It returns whether the selected implementation is available. +func Select(pkg, name string) bool { + if name == "" { + for _, i := range allImplementations { + if i.Package == pkg { + *i.Toggle = false + } + } + return true + } + if !available(pkg, name) { + return false + } + for _, i := range allImplementations { + if i.Package == pkg { + *i.Toggle = i.Name == name + } + } + return true +} + +func Reset(pkg string) { + for _, i := range allImplementations { + if i.Package == pkg { + *i.Toggle = i.Available + return + } + } +} diff --git a/crypto/internal/mlkem768/mlkem768.go b/crypto/internal/mlkem768/mlkem768.go deleted file mode 100644 index 08986fa3bed..00000000000 --- a/crypto/internal/mlkem768/mlkem768.go +++ /dev/null @@ -1,888 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package mlkem768 implements the quantum-resistant key encapsulation method -// ML-KEM (formerly known as Kyber). -// -// Only the recommended ML-KEM-768 parameter set is provided. -// -// The version currently implemented is the one specified by [NIST FIPS 203 ipd], -// with the unintentional transposition of the matrix A reverted to match the -// behavior of [Kyber version 3.0]. Future versions of this package might -// introduce backwards incompatible changes to implement changes to FIPS 203. -// -// [Kyber version 3.0]: https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf -// [NIST FIPS 203 ipd]: https://doi.org/10.6028/NIST.FIPS.203.ipd -package mlkem768 - -// This package targets security, correctness, simplicity, readability, and -// reviewability as its primary goals. All critical operations are performed in -// constant time. -// -// Variable and function names, as well as code layout, are selected to -// facilitate reviewing the implementation against the NIST FIPS 203 ipd -// document. -// -// Reviewers unfamiliar with polynomials or linear algebra might find the -// background at https://words.filippo.io/kyber-math/ useful. - -import ( - "errors" - - "crypto/rand" - - "github.com/runZeroInc/excrypto/crypto/subtle" - "github.com/runZeroInc/excrypto/internal/byteorder" - - "github.com/runZeroInc/excrypto/x/crypto/sha3" -) - -const ( - // ML-KEM global constants. - n = 256 - q = 3329 - - log2q = 12 - - // ML-KEM-768 parameters. The code makes assumptions based on these values, - // they can't be changed blindly. - k = 3 - η = 2 - du = 10 - dv = 4 - - // encodingSizeX is the byte size of a ringElement or nttElement encoded - // by ByteEncode_X (FIPS 203 (DRAFT), Algorithm 4). - encodingSize12 = n * log2q / 8 - encodingSize10 = n * du / 8 - encodingSize4 = n * dv / 8 - encodingSize1 = n * 1 / 8 - - messageSize = encodingSize1 - decryptionKeySize = k * encodingSize12 - encryptionKeySize = k*encodingSize12 + 32 - - CiphertextSize = k*encodingSize10 + encodingSize4 - EncapsulationKeySize = encryptionKeySize - DecapsulationKeySize = decryptionKeySize + encryptionKeySize + 32 + 32 - SharedKeySize = 32 - SeedSize = 32 + 32 -) - -// A DecapsulationKey is the secret key used to decapsulate a shared key from a -// ciphertext. It includes various precomputed values. -type DecapsulationKey struct { - dk [DecapsulationKeySize]byte - encryptionKey - decryptionKey -} - -// Bytes returns the extended encoding of the decapsulation key, according to -// FIPS 203 (DRAFT). -func (dk *DecapsulationKey) Bytes() []byte { - var b [DecapsulationKeySize]byte - copy(b[:], dk.dk[:]) - return b[:] -} - -// EncapsulationKey returns the public encapsulation key necessary to produce -// ciphertexts. -func (dk *DecapsulationKey) EncapsulationKey() []byte { - var b [EncapsulationKeySize]byte - copy(b[:], dk.dk[decryptionKeySize:]) - return b[:] -} - -// encryptionKey is the parsed and expanded form of a PKE encryption key. -type encryptionKey struct { - t [k]nttElement // ByteDecode₁₂(ek[:384k]) - A [k * k]nttElement // A[i*k+j] = sampleNTT(ρ, j, i) -} - -// decryptionKey is the parsed and expanded form of a PKE decryption key. -type decryptionKey struct { - s [k]nttElement // ByteDecode₁₂(dk[:decryptionKeySize]) -} - -// GenerateKey generates a new decapsulation key, drawing random bytes from -// crypto/rand. The decapsulation key must be kept secret. -func GenerateKey() (*DecapsulationKey, error) { - // The actual logic is in a separate function to outline this allocation. - dk := &DecapsulationKey{} - return generateKey(dk) -} - -func generateKey(dk *DecapsulationKey) (*DecapsulationKey, error) { - var d [32]byte - if _, err := rand.Read(d[:]); err != nil { - return nil, errors.New("mlkem768: crypto/rand Read failed: " + err.Error()) - } - var z [32]byte - if _, err := rand.Read(z[:]); err != nil { - return nil, errors.New("mlkem768: crypto/rand Read failed: " + err.Error()) - } - return kemKeyGen(dk, &d, &z), nil -} - -// NewKeyFromSeed deterministically generates a decapsulation key from a 64-byte -// seed in the "d || z" form. The seed must be uniformly random. -func NewKeyFromSeed(seed []byte) (*DecapsulationKey, error) { - // The actual logic is in a separate function to outline this allocation. - dk := &DecapsulationKey{} - return newKeyFromSeed(dk, seed) -} - -func newKeyFromSeed(dk *DecapsulationKey, seed []byte) (*DecapsulationKey, error) { - if len(seed) != SeedSize { - return nil, errors.New("mlkem768: invalid seed length") - } - d := (*[32]byte)(seed[:32]) - z := (*[32]byte)(seed[32:]) - return kemKeyGen(dk, d, z), nil -} - -// NewKeyFromExtendedEncoding parses a decapsulation key from its FIPS 203 -// (DRAFT) extended encoding. -func NewKeyFromExtendedEncoding(decapsulationKey []byte) (*DecapsulationKey, error) { - // The actual logic is in a separate function to outline this allocation. - dk := &DecapsulationKey{} - return newKeyFromExtendedEncoding(dk, decapsulationKey) -} - -func newKeyFromExtendedEncoding(dk *DecapsulationKey, dkBytes []byte) (*DecapsulationKey, error) { - if len(dkBytes) != DecapsulationKeySize { - return nil, errors.New("mlkem768: invalid decapsulation key length") - } - - // Note that we don't check that H(ek) matches ekPKE, as that's not - // specified in FIPS 203 (DRAFT). This is one reason to prefer the seed - // private key format. - dk.dk = [DecapsulationKeySize]byte(dkBytes) - - dkPKE := dkBytes[:decryptionKeySize] - if err := parseDK(&dk.decryptionKey, dkPKE); err != nil { - return nil, err - } - - ekPKE := dkBytes[decryptionKeySize : decryptionKeySize+encryptionKeySize] - if err := parseEK(&dk.encryptionKey, ekPKE); err != nil { - return nil, err - } - - return dk, nil -} - -// kemKeyGen generates a decapsulation key. -// -// It implements ML-KEM.KeyGen according to FIPS 203 (DRAFT), Algorithm 15, and -// K-PKE.KeyGen according to FIPS 203 (DRAFT), Algorithm 12. The two are merged -// to save copies and allocations. -func kemKeyGen(dk *DecapsulationKey, d, z *[32]byte) *DecapsulationKey { - if dk == nil { - dk = &DecapsulationKey{} - } - - G := sha3.Sum512(d[:]) - ρ, σ := G[:32], G[32:] - - A := &dk.A - for i := byte(0); i < k; i++ { - for j := byte(0); j < k; j++ { - // Note that this is consistent with Kyber round 3, rather than with - // the initial draft of FIPS 203, because NIST signaled that the - // change was involuntary and will be reverted. - A[i*k+j] = sampleNTT(ρ, j, i) - } - } - - var N byte - s := &dk.s - for i := range s { - s[i] = ntt(samplePolyCBD(σ, N)) - N++ - } - e := make([]nttElement, k) - for i := range e { - e[i] = ntt(samplePolyCBD(σ, N)) - N++ - } - - t := &dk.t - for i := range t { // t = A ◦ s + e - t[i] = e[i] - for j := range s { - t[i] = polyAdd(t[i], nttMul(A[i*k+j], s[j])) - } - } - - // dkPKE ← ByteEncode₁₂(s) - // ekPKE ← ByteEncode₁₂(t) || ρ - // ek ← ekPKE - // dk ← dkPKE || ek || H(ek) || z - dkB := dk.dk[:0] - - for i := range s { - dkB = polyByteEncode(dkB, s[i]) - } - - for i := range t { - dkB = polyByteEncode(dkB, t[i]) - } - dkB = append(dkB, ρ...) - - H := sha3.New256() - H.Write(dkB[decryptionKeySize:]) - dkB = H.Sum(dkB) - - dkB = append(dkB, z[:]...) - - if len(dkB) != len(dk.dk) { - panic("mlkem768: internal error: invalid decapsulation key size") - } - - return dk -} - -// Encapsulate generates a shared key and an associated ciphertext from an -// encapsulation key, drawing random bytes from crypto/rand. -// If the encapsulation key is not valid, Encapsulate returns an error. -// -// The shared key must be kept secret. -func Encapsulate(encapsulationKey []byte) (ciphertext, sharedKey []byte, err error) { - // The actual logic is in a separate function to outline this allocation. - var cc [CiphertextSize]byte - return encapsulate(&cc, encapsulationKey) -} - -func encapsulate(cc *[CiphertextSize]byte, encapsulationKey []byte) (ciphertext, sharedKey []byte, err error) { - if len(encapsulationKey) != EncapsulationKeySize { - return nil, nil, errors.New("mlkem768: invalid encapsulation key length") - } - var m [messageSize]byte - if _, err := rand.Read(m[:]); err != nil { - return nil, nil, errors.New("mlkem768: crypto/rand Read failed: " + err.Error()) - } - return kemEncaps(cc, encapsulationKey, &m) -} - -// kemEncaps generates a shared key and an associated ciphertext. -// -// It implements ML-KEM.Encaps according to FIPS 203 (DRAFT), Algorithm 16. -func kemEncaps(cc *[CiphertextSize]byte, ek []byte, m *[messageSize]byte) (c, K []byte, err error) { - if cc == nil { - cc = &[CiphertextSize]byte{} - } - - H := sha3.Sum256(ek[:]) - g := sha3.New512() - g.Write(m[:]) - g.Write(H[:]) - G := g.Sum(nil) - K, r := G[:SharedKeySize], G[SharedKeySize:] - var ex encryptionKey - if err := parseEK(&ex, ek[:]); err != nil { - return nil, nil, err - } - c = pkeEncrypt(cc, &ex, m, r) - return c, K, nil -} - -// parseEK parses an encryption key from its encoded form. -// -// It implements the initial stages of K-PKE.Encrypt according to FIPS 203 -// (DRAFT), Algorithm 13. -func parseEK(ex *encryptionKey, ekPKE []byte) error { - if len(ekPKE) != encryptionKeySize { - return errors.New("mlkem768: invalid encryption key length") - } - - for i := range ex.t { - var err error - ex.t[i], err = polyByteDecode[nttElement](ekPKE[:encodingSize12]) - if err != nil { - return err - } - ekPKE = ekPKE[encodingSize12:] - } - ρ := ekPKE - - for i := byte(0); i < k; i++ { - for j := byte(0); j < k; j++ { - // See the note in pkeKeyGen about the order of the indices being - // consistent with Kyber round 3. - ex.A[i*k+j] = sampleNTT(ρ, j, i) - } - } - - return nil -} - -// pkeEncrypt encrypt a plaintext message. -// -// It implements K-PKE.Encrypt according to FIPS 203 (DRAFT), Algorithm 13, -// although the computation of t and AT is done in parseEK. -func pkeEncrypt(cc *[CiphertextSize]byte, ex *encryptionKey, m *[messageSize]byte, rnd []byte) []byte { - var N byte - r, e1 := make([]nttElement, k), make([]ringElement, k) - for i := range r { - r[i] = ntt(samplePolyCBD(rnd, N)) - N++ - } - for i := range e1 { - e1[i] = samplePolyCBD(rnd, N) - N++ - } - e2 := samplePolyCBD(rnd, N) - - u := make([]ringElement, k) // NTT⁻¹(AT ◦ r) + e1 - for i := range u { - u[i] = e1[i] - for j := range r { - // Note that i and j are inverted, as we need the transposed of A. - u[i] = polyAdd(u[i], inverseNTT(nttMul(ex.A[j*k+i], r[j]))) - } - } - - μ := ringDecodeAndDecompress1(m) - - var vNTT nttElement // t⊺ ◦ r - for i := range ex.t { - vNTT = polyAdd(vNTT, nttMul(ex.t[i], r[i])) - } - v := polyAdd(polyAdd(inverseNTT(vNTT), e2), μ) - - c := cc[:0] - for _, f := range u { - c = ringCompressAndEncode10(c, f) - } - c = ringCompressAndEncode4(c, v) - - return c -} - -// Decapsulate generates a shared key from a ciphertext and a decapsulation key. -// If the ciphertext is not valid, Decapsulate returns an error. -// -// The shared key must be kept secret. -func Decapsulate(dk *DecapsulationKey, ciphertext []byte) (sharedKey []byte, err error) { - if len(ciphertext) != CiphertextSize { - return nil, errors.New("mlkem768: invalid ciphertext length") - } - c := (*[CiphertextSize]byte)(ciphertext) - return kemDecaps(dk, c), nil -} - -// kemDecaps produces a shared key from a ciphertext. -// -// It implements ML-KEM.Decaps according to FIPS 203 (DRAFT), Algorithm 17. -func kemDecaps(dk *DecapsulationKey, c *[CiphertextSize]byte) (K []byte) { - h := dk.dk[decryptionKeySize+encryptionKeySize : decryptionKeySize+encryptionKeySize+32] - z := dk.dk[decryptionKeySize+encryptionKeySize+32:] - - m := pkeDecrypt(&dk.decryptionKey, c) - g := sha3.New512() - g.Write(m[:]) - g.Write(h) - G := g.Sum(nil) - Kprime, r := G[:SharedKeySize], G[SharedKeySize:] - J := sha3.NewShake256() - J.Write(z) - J.Write(c[:]) - Kout := make([]byte, SharedKeySize) - J.Read(Kout) - var cc [CiphertextSize]byte - c1 := pkeEncrypt(&cc, &dk.encryptionKey, (*[32]byte)(m), r) - - subtle.ConstantTimeCopy(subtle.ConstantTimeCompare(c[:], c1), Kout, Kprime) - return Kout -} - -// parseDK parses a decryption key from its encoded form. -// -// It implements the computation of s from K-PKE.Decrypt according to FIPS 203 -// (DRAFT), Algorithm 14. -func parseDK(dx *decryptionKey, dkPKE []byte) error { - if len(dkPKE) != decryptionKeySize { - return errors.New("mlkem768: invalid decryption key length") - } - - for i := range dx.s { - f, err := polyByteDecode[nttElement](dkPKE[:encodingSize12]) - if err != nil { - return err - } - dx.s[i] = f - dkPKE = dkPKE[encodingSize12:] - } - - return nil -} - -// pkeDecrypt decrypts a ciphertext. -// -// It implements K-PKE.Decrypt according to FIPS 203 (DRAFT), Algorithm 14, -// although the computation of s is done in parseDK. -func pkeDecrypt(dx *decryptionKey, c *[CiphertextSize]byte) []byte { - u := make([]ringElement, k) - for i := range u { - b := (*[encodingSize10]byte)(c[encodingSize10*i : encodingSize10*(i+1)]) - u[i] = ringDecodeAndDecompress10(b) - } - - b := (*[encodingSize4]byte)(c[encodingSize10*k:]) - v := ringDecodeAndDecompress4(b) - - var mask nttElement // s⊺ ◦ NTT(u) - for i := range dx.s { - mask = polyAdd(mask, nttMul(dx.s[i], ntt(u[i]))) - } - w := polySub(v, inverseNTT(mask)) - - return ringCompressAndEncode1(nil, w) -} - -// fieldElement is an integer modulo q, an element of ℤ_q. It is always reduced. -type fieldElement uint16 - -// fieldCheckReduced checks that a value a is < q. -func fieldCheckReduced(a uint16) (fieldElement, error) { - if a >= q { - return 0, errors.New("unreduced field element") - } - return fieldElement(a), nil -} - -// fieldReduceOnce reduces a value a < 2q. -func fieldReduceOnce(a uint16) fieldElement { - x := a - q - // If x underflowed, then x >= 2¹⁶ - q > 2¹⁵, so the top bit is set. - x += (x >> 15) * q - return fieldElement(x) -} - -func fieldAdd(a, b fieldElement) fieldElement { - x := uint16(a + b) - return fieldReduceOnce(x) -} - -func fieldSub(a, b fieldElement) fieldElement { - x := uint16(a - b + q) - return fieldReduceOnce(x) -} - -const ( - barrettMultiplier = 5039 // 2¹² * 2¹² / q - barrettShift = 24 // log₂(2¹² * 2¹²) -) - -// fieldReduce reduces a value a < 2q² using Barrett reduction, to avoid -// potentially variable-time division. -func fieldReduce(a uint32) fieldElement { - quotient := uint32((uint64(a) * barrettMultiplier) >> barrettShift) - return fieldReduceOnce(uint16(a - quotient*q)) -} - -func fieldMul(a, b fieldElement) fieldElement { - x := uint32(a) * uint32(b) - return fieldReduce(x) -} - -// fieldMulSub returns a * (b - c). This operation is fused to save a -// fieldReduceOnce after the subtraction. -func fieldMulSub(a, b, c fieldElement) fieldElement { - x := uint32(a) * uint32(b-c+q) - return fieldReduce(x) -} - -// fieldAddMul returns a * b + c * d. This operation is fused to save a -// fieldReduceOnce and a fieldReduce. -func fieldAddMul(a, b, c, d fieldElement) fieldElement { - x := uint32(a) * uint32(b) - x += uint32(c) * uint32(d) - return fieldReduce(x) -} - -// compress maps a field element uniformly to the range 0 to 2ᵈ-1, according to -// FIPS 203 (DRAFT), Definition 4.5. -func compress(x fieldElement, d uint8) uint16 { - // We want to compute (x * 2ᵈ) / q, rounded to nearest integer, with 1/2 - // rounding up (see FIPS 203 (DRAFT), Section 2.3). - - // Barrett reduction produces a quotient and a remainder in the range [0, 2q), - // such that dividend = quotient * q + remainder. - dividend := uint32(x) << d // x * 2ᵈ - quotient := uint32(uint64(dividend) * barrettMultiplier >> barrettShift) - remainder := dividend - quotient*q - - // Since the remainder is in the range [0, 2q), not [0, q), we need to - // portion it into three spans for rounding. - // - // [ 0, q/2 ) -> round to 0 - // [ q/2, q + q/2 ) -> round to 1 - // [ q + q/2, 2q ) -> round to 2 - // - // We can convert that to the following logic: add 1 if remainder > q/2, - // then add 1 again if remainder > q + q/2. - // - // Note that if remainder > x, then ⌊x⌋ - remainder underflows, and the top - // bit of the difference will be set. - quotient += (q/2 - remainder) >> 31 & 1 - quotient += (q + q/2 - remainder) >> 31 & 1 - - // quotient might have overflowed at this point, so reduce it by masking. - var mask uint32 = (1 << d) - 1 - return uint16(quotient & mask) -} - -// decompress maps a number x between 0 and 2ᵈ-1 uniformly to the full range of -// field elements, according to FIPS 203 (DRAFT), Definition 4.6. -func decompress(y uint16, d uint8) fieldElement { - // We want to compute (y * q) / 2ᵈ, rounded to nearest integer, with 1/2 - // rounding up (see FIPS 203 (DRAFT), Section 2.3). - - dividend := uint32(y) * q - quotient := dividend >> d // (y * q) / 2ᵈ - - // The d'th least-significant bit of the dividend (the most significant bit - // of the remainder) is 1 for the top half of the values that divide to the - // same quotient, which are the ones that round up. - quotient += dividend >> (d - 1) & 1 - - // quotient is at most (2¹¹-1) * q / 2¹¹ + 1 = 3328, so it didn't overflow. - return fieldElement(quotient) -} - -// ringElement is a polynomial, an element of R_q, represented as an array -// according to FIPS 203 (DRAFT), Section 2.4. -type ringElement [n]fieldElement - -// polyAdd adds two ringElements or nttElements. -func polyAdd[T ~[n]fieldElement](a, b T) (s T) { - for i := range s { - s[i] = fieldAdd(a[i], b[i]) - } - return s -} - -// polySub subtracts two ringElements or nttElements. -func polySub[T ~[n]fieldElement](a, b T) (s T) { - for i := range s { - s[i] = fieldSub(a[i], b[i]) - } - return s -} - -// polyByteEncode appends the 384-byte encoding of f to b. -// -// It implements ByteEncode₁₂, according to FIPS 203 (DRAFT), Algorithm 4. -func polyByteEncode[T ~[n]fieldElement](b []byte, f T) []byte { - out, B := sliceForAppend(b, encodingSize12) - for i := 0; i < n; i += 2 { - x := uint32(f[i]) | uint32(f[i+1])<<12 - B[0] = uint8(x) - B[1] = uint8(x >> 8) - B[2] = uint8(x >> 16) - B = B[3:] - } - return out -} - -// polyByteDecode decodes the 384-byte encoding of a polynomial, checking that -// all the coefficients are properly reduced. This achieves the "Modulus check" -// step of ML-KEM Encapsulation Input Validation. -// -// polyByteDecode is also used in ML-KEM Decapsulation, where the input -// validation is not required, but implicitly allowed by the specification. -// -// It implements ByteDecode₁₂, according to FIPS 203 (DRAFT), Algorithm 5. -func polyByteDecode[T ~[n]fieldElement](b []byte) (T, error) { - if len(b) != encodingSize12 { - return T{}, errors.New("mlkem768: invalid encoding length") - } - var f T - for i := 0; i < n; i += 2 { - d := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 - const mask12 = 0b1111_1111_1111 - var err error - if f[i], err = fieldCheckReduced(uint16(d & mask12)); err != nil { - return T{}, errors.New("mlkem768: invalid polynomial encoding") - } - if f[i+1], err = fieldCheckReduced(uint16(d >> 12)); err != nil { - return T{}, errors.New("mlkem768: invalid polynomial encoding") - } - b = b[3:] - } - return f, nil -} - -// sliceForAppend takes a slice and a requested number of bytes. It returns a -// slice with the contents of the given slice followed by that many bytes and a -// second slice that aliases into it and contains only the extra bytes. If the -// original slice has sufficient capacity then no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// ringCompressAndEncode1 appends a 32-byte encoding of a ring element to s, -// compressing one coefficients per bit. -// -// It implements Compress₁, according to FIPS 203 (DRAFT), Definition 4.5, -// followed by ByteEncode₁, according to FIPS 203 (DRAFT), Algorithm 4. -func ringCompressAndEncode1(s []byte, f ringElement) []byte { - s, b := sliceForAppend(s, encodingSize1) - for i := range b { - b[i] = 0 - } - for i := range f { - b[i/8] |= uint8(compress(f[i], 1) << (i % 8)) - } - return s -} - -// ringDecodeAndDecompress1 decodes a 32-byte slice to a ring element where each -// bit is mapped to 0 or ⌈q/2⌋. -// -// It implements ByteDecode₁, according to FIPS 203 (DRAFT), Algorithm 5, -// followed by Decompress₁, according to FIPS 203 (DRAFT), Definition 4.6. -func ringDecodeAndDecompress1(b *[encodingSize1]byte) ringElement { - var f ringElement - for i := range f { - b_i := b[i/8] >> (i % 8) & 1 - const halfQ = (q + 1) / 2 // ⌈q/2⌋, rounded up per FIPS 203 (DRAFT), Section 2.3 - f[i] = fieldElement(b_i) * halfQ // 0 decompresses to 0, and 1 to ⌈q/2⌋ - } - return f -} - -// ringCompressAndEncode4 appends a 128-byte encoding of a ring element to s, -// compressing two coefficients per byte. -// -// It implements Compress₄, according to FIPS 203 (DRAFT), Definition 4.5, -// followed by ByteEncode₄, according to FIPS 203 (DRAFT), Algorithm 4. -func ringCompressAndEncode4(s []byte, f ringElement) []byte { - s, b := sliceForAppend(s, encodingSize4) - for i := 0; i < n; i += 2 { - b[i/2] = uint8(compress(f[i], 4) | compress(f[i+1], 4)<<4) - } - return s -} - -// ringDecodeAndDecompress4 decodes a 128-byte encoding of a ring element where -// each four bits are mapped to an equidistant distribution. -// -// It implements ByteDecode₄, according to FIPS 203 (DRAFT), Algorithm 5, -// followed by Decompress₄, according to FIPS 203 (DRAFT), Definition 4.6. -func ringDecodeAndDecompress4(b *[encodingSize4]byte) ringElement { - var f ringElement - for i := 0; i < n; i += 2 { - f[i] = fieldElement(decompress(uint16(b[i/2]&0b1111), 4)) - f[i+1] = fieldElement(decompress(uint16(b[i/2]>>4), 4)) - } - return f -} - -// ringCompressAndEncode10 appends a 320-byte encoding of a ring element to s, -// compressing four coefficients per five bytes. -// -// It implements Compress₁₀, according to FIPS 203 (DRAFT), Definition 4.5, -// followed by ByteEncode₁₀, according to FIPS 203 (DRAFT), Algorithm 4. -func ringCompressAndEncode10(s []byte, f ringElement) []byte { - s, b := sliceForAppend(s, encodingSize10) - for i := 0; i < n; i += 4 { - var x uint64 - x |= uint64(compress(f[i+0], 10)) - x |= uint64(compress(f[i+1], 10)) << 10 - x |= uint64(compress(f[i+2], 10)) << 20 - x |= uint64(compress(f[i+3], 10)) << 30 - b[0] = uint8(x) - b[1] = uint8(x >> 8) - b[2] = uint8(x >> 16) - b[3] = uint8(x >> 24) - b[4] = uint8(x >> 32) - b = b[5:] - } - return s -} - -// ringDecodeAndDecompress10 decodes a 320-byte encoding of a ring element where -// each ten bits are mapped to an equidistant distribution. -// -// It implements ByteDecode₁₀, according to FIPS 203 (DRAFT), Algorithm 5, -// followed by Decompress₁₀, according to FIPS 203 (DRAFT), Definition 4.6. -func ringDecodeAndDecompress10(bb *[encodingSize10]byte) ringElement { - b := bb[:] - var f ringElement - for i := 0; i < n; i += 4 { - x := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 - b = b[5:] - f[i] = fieldElement(decompress(uint16(x>>0&0b11_1111_1111), 10)) - f[i+1] = fieldElement(decompress(uint16(x>>10&0b11_1111_1111), 10)) - f[i+2] = fieldElement(decompress(uint16(x>>20&0b11_1111_1111), 10)) - f[i+3] = fieldElement(decompress(uint16(x>>30&0b11_1111_1111), 10)) - } - return f -} - -// samplePolyCBD draws a ringElement from the special Dη distribution given a -// stream of random bytes generated by the PRF function, according to FIPS 203 -// (DRAFT), Algorithm 7 and Definition 4.1. -func samplePolyCBD(s []byte, b byte) ringElement { - prf := sha3.NewShake256() - prf.Write(s) - prf.Write([]byte{b}) - B := make([]byte, 128) - prf.Read(B) - - // SamplePolyCBD simply draws four (2η) bits for each coefficient, and adds - // the first two and subtracts the last two. - - var f ringElement - for i := 0; i < n; i += 2 { - b := B[i/2] - b_7, b_6, b_5, b_4 := b>>7, b>>6&1, b>>5&1, b>>4&1 - b_3, b_2, b_1, b_0 := b>>3&1, b>>2&1, b>>1&1, b&1 - f[i] = fieldSub(fieldElement(b_0+b_1), fieldElement(b_2+b_3)) - f[i+1] = fieldSub(fieldElement(b_4+b_5), fieldElement(b_6+b_7)) - } - return f -} - -// nttElement is an NTT representation, an element of T_q, represented as an -// array according to FIPS 203 (DRAFT), Section 2.4. -type nttElement [n]fieldElement - -// gammas are the values ζ^2BitRev7(i)+1 mod q for each index i. -var gammas = [128]fieldElement{17, 3312, 2761, 568, 583, 2746, 2649, 680, 1637, 1692, 723, 2606, 2288, 1041, 1100, 2229, 1409, 1920, 2662, 667, 3281, 48, 233, 3096, 756, 2573, 2156, 1173, 3015, 314, 3050, 279, 1703, 1626, 1651, 1678, 2789, 540, 1789, 1540, 1847, 1482, 952, 2377, 1461, 1868, 2687, 642, 939, 2390, 2308, 1021, 2437, 892, 2388, 941, 733, 2596, 2337, 992, 268, 3061, 641, 2688, 1584, 1745, 2298, 1031, 2037, 1292, 3220, 109, 375, 2954, 2549, 780, 2090, 1239, 1645, 1684, 1063, 2266, 319, 3010, 2773, 556, 757, 2572, 2099, 1230, 561, 2768, 2466, 863, 2594, 735, 2804, 525, 1092, 2237, 403, 2926, 1026, 2303, 1143, 2186, 2150, 1179, 2775, 554, 886, 2443, 1722, 1607, 1212, 2117, 1874, 1455, 1029, 2300, 2110, 1219, 2935, 394, 885, 2444, 2154, 1175} - -// nttMul multiplies two nttElements. -// -// It implements MultiplyNTTs, according to FIPS 203 (DRAFT), Algorithm 10. -func nttMul(f, g nttElement) nttElement { - var h nttElement - // We use i += 2 for bounds check elimination. See https://go.dev/issue/66826. - for i := 0; i < 256; i += 2 { - a0, a1 := f[i], f[i+1] - b0, b1 := g[i], g[i+1] - h[i] = fieldAddMul(a0, b0, fieldMul(a1, b1), gammas[i/2]) - h[i+1] = fieldAddMul(a0, b1, a1, b0) - } - return h -} - -// zetas are the values ζ^BitRev7(k) mod q for each index k. -var zetas = [128]fieldElement{1, 1729, 2580, 3289, 2642, 630, 1897, 848, 1062, 1919, 193, 797, 2786, 3260, 569, 1746, 296, 2447, 1339, 1476, 3046, 56, 2240, 1333, 1426, 2094, 535, 2882, 2393, 2879, 1974, 821, 289, 331, 3253, 1756, 1197, 2304, 2277, 2055, 650, 1977, 2513, 632, 2865, 33, 1320, 1915, 2319, 1435, 807, 452, 1438, 2868, 1534, 2402, 2647, 2617, 1481, 648, 2474, 3110, 1227, 910, 17, 2761, 583, 2649, 1637, 723, 2288, 1100, 1409, 2662, 3281, 233, 756, 2156, 3015, 3050, 1703, 1651, 2789, 1789, 1847, 952, 1461, 2687, 939, 2308, 2437, 2388, 733, 2337, 268, 641, 1584, 2298, 2037, 3220, 375, 2549, 2090, 1645, 1063, 319, 2773, 757, 2099, 561, 2466, 2594, 2804, 1092, 403, 1026, 1143, 2150, 2775, 886, 1722, 1212, 1874, 1029, 2110, 2935, 885, 2154} - -// ntt maps a ringElement to its nttElement representation. -// -// It implements NTT, according to FIPS 203 (DRAFT), Algorithm 8. -func ntt(f ringElement) nttElement { - k := 1 - for len := 128; len >= 2; len /= 2 { - for start := 0; start < 256; start += 2 * len { - zeta := zetas[k] - k++ - // Bounds check elimination hint. - f, flen := f[start:start+len], f[start+len:start+len+len] - for j := 0; j < len; j++ { - t := fieldMul(zeta, flen[j]) - flen[j] = fieldSub(f[j], t) - f[j] = fieldAdd(f[j], t) - } - } - } - return nttElement(f) -} - -// inverseNTT maps a nttElement back to the ringElement it represents. -// -// It implements NTT⁻¹, according to FIPS 203 (DRAFT), Algorithm 9. -func inverseNTT(f nttElement) ringElement { - k := 127 - for len := 2; len <= 128; len *= 2 { - for start := 0; start < 256; start += 2 * len { - zeta := zetas[k] - k-- - // Bounds check elimination hint. - f, flen := f[start:start+len], f[start+len:start+len+len] - for j := 0; j < len; j++ { - t := f[j] - f[j] = fieldAdd(t, flen[j]) - flen[j] = fieldMulSub(zeta, flen[j], t) - } - } - } - for i := range f { - f[i] = fieldMul(f[i], 3303) // 3303 = 128⁻¹ mod q - } - return ringElement(f) -} - -// sampleNTT draws a uniformly random nttElement from a stream of uniformly -// random bytes generated by the XOF function, according to FIPS 203 (DRAFT), -// Algorithm 6 and Definition 4.2. -func sampleNTT(rho []byte, ii, jj byte) nttElement { - B := sha3.NewShake128() - B.Write(rho) - B.Write([]byte{ii, jj}) - - // SampleNTT essentially draws 12 bits at a time from r, interprets them in - // little-endian, and rejects values higher than q, until it drew 256 - // values. (The rejection rate is approximately 19%.) - // - // To do this from a bytes stream, it draws three bytes at a time, and - // splits them into two uint16 appropriately masked. - // - // r₀ r₁ r₂ - // |- - - - - - - -|- - - - - - - -|- - - - - - - -| - // - // Uint16(r₀ || r₁) - // |- - - - - - - - - - - - - - - -| - // |- - - - - - - - - - - -| - // d₁ - // - // Uint16(r₁ || r₂) - // |- - - - - - - - - - - - - - - -| - // |- - - - - - - - - - - -| - // d₂ - // - // Note that in little-endian, the rightmost bits are the most significant - // bits (dropped with a mask) and the leftmost bits are the least - // significant bits (dropped with a right shift). - - var a nttElement - var j int // index into a - var buf [24]byte // buffered reads from B - off := len(buf) // index into buf, starts in a "buffer fully consumed" state - for { - if off >= len(buf) { - B.Read(buf[:]) - off = 0 - } - d1 := byteorder.LeUint16(buf[off:]) & 0b1111_1111_1111 - d2 := byteorder.LeUint16(buf[off+1:]) >> 4 - off += 3 - if d1 < q { - a[j] = fieldElement(d1) - j++ - } - if j >= len(a) { - break - } - if d2 < q { - a[j] = fieldElement(d2) - j++ - } - if j >= len(a) { - break - } - } - return a -} diff --git a/crypto/internal/mlkem768/mlkem768_test.go b/crypto/internal/mlkem768/mlkem768_test.go deleted file mode 100644 index 52b31b9ff8c..00000000000 --- a/crypto/internal/mlkem768/mlkem768_test.go +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mlkem768 - -import ( - "bytes" - _ "embed" - "encoding/hex" - "errors" - "flag" - "math/big" - "strconv" - "testing" - - "crypto/rand" - - "github.com/runZeroInc/excrypto/x/crypto/sha3" -) - -func TestFieldReduce(t *testing.T) { - for a := uint32(0); a < 2*q*q; a++ { - got := fieldReduce(a) - exp := fieldElement(a % q) - if got != exp { - t.Fatalf("reduce(%d) = %d, expected %d", a, got, exp) - } - } -} - -func TestFieldAdd(t *testing.T) { - for a := fieldElement(0); a < q; a++ { - for b := fieldElement(0); b < q; b++ { - got := fieldAdd(a, b) - exp := (a + b) % q - if got != exp { - t.Fatalf("%d + %d = %d, expected %d", a, b, got, exp) - } - } - } -} - -func TestFieldSub(t *testing.T) { - for a := fieldElement(0); a < q; a++ { - for b := fieldElement(0); b < q; b++ { - got := fieldSub(a, b) - exp := (a - b + q) % q - if got != exp { - t.Fatalf("%d - %d = %d, expected %d", a, b, got, exp) - } - } - } -} - -func TestFieldMul(t *testing.T) { - for a := fieldElement(0); a < q; a++ { - for b := fieldElement(0); b < q; b++ { - got := fieldMul(a, b) - exp := fieldElement((uint32(a) * uint32(b)) % q) - if got != exp { - t.Fatalf("%d * %d = %d, expected %d", a, b, got, exp) - } - } - } -} - -func TestDecompressCompress(t *testing.T) { - for _, bits := range []uint8{1, 4, 10} { - for a := uint16(0); a < 1<= q { - t.Fatalf("decompress(%d, %d) = %d >= q", a, bits, f) - } - got := compress(f, bits) - if got != a { - t.Fatalf("compress(decompress(%d, %d), %d) = %d", a, bits, bits, got) - } - } - - for a := fieldElement(0); a < q; a++ { - c := compress(a, bits) - if c >= 1<= 2^bits", a, bits, c) - } - got := decompress(c, bits) - diff := min(a-got, got-a, a-got+q, got-a+q) - ceil := q / (1 << bits) - if diff > fieldElement(ceil) { - t.Fatalf("decompress(compress(%d, %d), %d) = %d (diff %d, max diff %d)", - a, bits, bits, got, diff, ceil) - } - } - } -} - -func CompressRat(x fieldElement, d uint8) uint16 { - if x >= q { - panic("x out of range") - } - if d <= 0 || d >= 12 { - panic("d out of range") - } - - precise := big.NewRat((1<= 1<= 12 { - panic("d out of range") - } - - precise := big.NewRat(q*int64(y), 1<>7 != 0 { - panic("not 7 bits") - } - var r uint8 - r |= n >> 6 & 0b0000_0001 - r |= n >> 4 & 0b0000_0010 - r |= n >> 2 & 0b0000_0100 - r |= n /**/ & 0b0000_1000 - r |= n << 2 & 0b0001_0000 - r |= n << 4 & 0b0010_0000 - r |= n << 6 & 0b0100_0000 - return r -} - -func TestZetas(t *testing.T) { - ζ := big.NewInt(17) - q := big.NewInt(q) - for k, zeta := range zetas { - // ζ^BitRev7(k) mod q - exp := new(big.Int).Exp(ζ, big.NewInt(int64(BitRev7(uint8(k)))), q) - if big.NewInt(int64(zeta)).Cmp(exp) != 0 { - t.Errorf("zetas[%d] = %v, expected %v", k, zeta, exp) - } - } -} - -func TestGammas(t *testing.T) { - ζ := big.NewInt(17) - q := big.NewInt(q) - for k, gamma := range gammas { - // ζ^2BitRev7(i)+1 - exp := new(big.Int).Exp(ζ, big.NewInt(int64(BitRev7(uint8(k)))*2+1), q) - if big.NewInt(int64(gamma)).Cmp(exp) != 0 { - t.Errorf("gammas[%d] = %v, expected %v", k, gamma, exp) - } - } -} - -func TestRoundTrip(t *testing.T) { - dk, err := GenerateKey() - if err != nil { - t.Fatal(err) - } - c, Ke, err := Encapsulate(dk.EncapsulationKey()) - if err != nil { - t.Fatal(err) - } - Kd, err := Decapsulate(dk, c) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(Ke, Kd) { - t.Fail() - } - - dk1, err := GenerateKey() - if err != nil { - t.Fatal(err) - } - if bytes.Equal(dk.EncapsulationKey(), dk1.EncapsulationKey()) { - t.Fail() - } - if bytes.Equal(dk.Bytes(), dk1.Bytes()) { - t.Fail() - } - if bytes.Equal(dk.Bytes()[EncapsulationKeySize-32:], dk1.Bytes()[EncapsulationKeySize-32:]) { - t.Fail() - } - - c1, Ke1, err := Encapsulate(dk.EncapsulationKey()) - if err != nil { - t.Fatal(err) - } - if bytes.Equal(c, c1) { - t.Fail() - } - if bytes.Equal(Ke, Ke1) { - t.Fail() - } -} - -func TestBadLengths(t *testing.T) { - dk, err := GenerateKey() - if err != nil { - t.Fatal(err) - } - ek := dk.EncapsulationKey() - - for i := 0; i < len(ek)-1; i++ { - if _, _, err := Encapsulate(ek[:i]); err == nil { - t.Errorf("expected error for ek length %d", i) - } - } - ekLong := ek - for i := 0; i < 100; i++ { - ekLong = append(ekLong, 0) - if _, _, err := Encapsulate(ekLong); err == nil { - t.Errorf("expected error for ek length %d", len(ekLong)) - } - } - - c, _, err := Encapsulate(ek) - if err != nil { - t.Fatal(err) - } - - for i := 0; i < len(dk.Bytes())-1; i++ { - if _, err := NewKeyFromExtendedEncoding(dk.Bytes()[:i]); err == nil { - t.Errorf("expected error for dk length %d", i) - } - } - dkLong := dk.Bytes() - for i := 0; i < 100; i++ { - dkLong = append(dkLong, 0) - if _, err := NewKeyFromExtendedEncoding(dkLong); err == nil { - t.Errorf("expected error for dk length %d", len(dkLong)) - } - } - - for i := 0; i < len(c)-1; i++ { - if _, err := Decapsulate(dk, c[:i]); err == nil { - t.Errorf("expected error for c length %d", i) - } - } - cLong := c - for i := 0; i < 100; i++ { - cLong = append(cLong, 0) - if _, err := Decapsulate(dk, cLong); err == nil { - t.Errorf("expected error for c length %d", len(cLong)) - } - } -} - -func EncapsulateDerand(ek, m []byte) (c, K []byte, err error) { - if len(m) != messageSize { - return nil, nil, errors.New("bad message length") - } - return kemEncaps(nil, ek, (*[messageSize]byte)(m)) -} - -func DecapsulateFromBytes(dkBytes []byte, c []byte) ([]byte, error) { - dk, err := NewKeyFromExtendedEncoding(dkBytes) - if err != nil { - return nil, err - } - return Decapsulate(dk, c) -} - -func GenerateKeyDerand(t testing.TB, d, z []byte) ([]byte, *DecapsulationKey) { - if len(d) != 32 || len(z) != 32 { - t.Fatal("bad length") - } - dk := kemKeyGen(nil, (*[32]byte)(d), (*[32]byte)(z)) - return dk.EncapsulationKey(), dk -} - -var millionFlag = flag.Bool("million", false, "run the million vector test") - -// TestPQCrystalsAccumulated accumulates the 10k vectors generated by the -// reference implementation and checks the hash of the result, to avoid checking -// in 150MB of test vectors. -func TestPQCrystalsAccumulated(t *testing.T) { - n := 10000 - expected := "f7db260e1137a742e05fe0db9525012812b004d29040a5b606aad3d134b548d3" - if testing.Short() { - n = 100 - expected = "8d0c478ead6037897a0da6be21e5399545babf5fc6dd10c061c99b7dee2bf0dc" - } - if *millionFlag { - n = 1000000 - expected = "70090cc5842aad0ec43d5042c783fae9bc320c047b5dafcb6e134821db02384d" - } - - s := sha3.NewShake128() - o := sha3.NewShake128() - d := make([]byte, 32) - z := make([]byte, 32) - msg := make([]byte, 32) - ct1 := make([]byte, CiphertextSize) - - for i := 0; i < n; i++ { - s.Read(d) - s.Read(z) - ek, dk := GenerateKeyDerand(t, d, z) - o.Write(ek) - o.Write(dk.Bytes()) - - s.Read(msg) - ct, k, err := EncapsulateDerand(ek, msg) - if err != nil { - t.Fatal(err) - } - o.Write(ct) - o.Write(k) - - kk, err := Decapsulate(dk, ct) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(kk, k) { - t.Errorf("k: got %x, expected %x", kk, k) - } - - s.Read(ct1) - k1, err := Decapsulate(dk, ct1) - if err != nil { - t.Fatal(err) - } - o.Write(k1) - } - - got := hex.EncodeToString(o.Sum(nil)) - if got != expected { - t.Errorf("got %s, expected %s", got, expected) - } -} - -var sink byte - -func BenchmarkKeyGen(b *testing.B) { - var dk DecapsulationKey - var d, z [32]byte - rand.Read(d[:]) - rand.Read(z[:]) - b.ResetTimer() - for i := 0; i < b.N; i++ { - dk := kemKeyGen(&dk, &d, &z) - sink ^= dk.EncapsulationKey()[0] - } -} - -func BenchmarkEncaps(b *testing.B) { - d := make([]byte, 32) - rand.Read(d) - z := make([]byte, 32) - rand.Read(z) - var m [messageSize]byte - rand.Read(m[:]) - ek, _ := GenerateKeyDerand(b, d, z) - var c [CiphertextSize]byte - b.ResetTimer() - for i := 0; i < b.N; i++ { - c, K, err := kemEncaps(&c, ek, &m) - if err != nil { - b.Fatal(err) - } - sink ^= c[0] ^ K[0] - } -} - -func BenchmarkDecaps(b *testing.B) { - d := make([]byte, 32) - rand.Read(d) - z := make([]byte, 32) - rand.Read(z) - m := make([]byte, 32) - rand.Read(m) - ek, dk := GenerateKeyDerand(b, d, z) - c, _, err := EncapsulateDerand(ek, m) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - K := kemDecaps(dk, (*[CiphertextSize]byte)(c)) - sink ^= K[0] - } -} - -func BenchmarkRoundTrip(b *testing.B) { - dk, err := GenerateKey() - if err != nil { - b.Fatal(err) - } - ek := dk.EncapsulationKey() - c, _, err := Encapsulate(ek) - if err != nil { - b.Fatal(err) - } - b.Run("Alice", func(b *testing.B) { - for i := 0; i < b.N; i++ { - dkS, err := GenerateKey() - if err != nil { - b.Fatal(err) - } - ekS := dkS.EncapsulationKey() - sink ^= ekS[0] - - Ks, err := Decapsulate(dk, c) - if err != nil { - b.Fatal(err) - } - sink ^= Ks[0] - } - }) - b.Run("Bob", func(b *testing.B) { - for i := 0; i < b.N; i++ { - cS, Ks, err := Encapsulate(ek) - if err != nil { - b.Fatal(err) - } - sink ^= cS[0] ^ Ks[0] - } - }) -} diff --git a/crypto/internal/nistec/_asm/go.mod b/crypto/internal/nistec/_asm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/nistec/_asm/go.sum b/crypto/internal/nistec/_asm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/internal/nistec/nistec_test.go b/crypto/internal/nistec/nistec_test.go deleted file mode 100644 index 159c104fa34..00000000000 --- a/crypto/internal/nistec/nistec_test.go +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package nistec_test - -import ( - "bytes" - "fmt" - "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/crypto/internal/nistec" - "github.com/runZeroInc/excrypto/internal/testenv" - "math/big" - "math/rand" - "testing" -) - -func TestAllocations(t *testing.T) { - testenv.SkipIfOptimizationOff(t) - - t.Run("P224", func(t *testing.T) { - if allocs := testing.AllocsPerRun(10, func() { - p := nistec.NewP224Point().SetGenerator() - scalar := make([]byte, 28) - rand.Read(scalar) - p.ScalarBaseMult(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := nistec.NewP224Point().SetBytes(out); err != nil { - t.Fatal(err) - } - out = p.BytesCompressed() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } - }) - t.Run("P256", func(t *testing.T) { - if allocs := testing.AllocsPerRun(10, func() { - p := nistec.NewP256Point().SetGenerator() - scalar := make([]byte, 32) - rand.Read(scalar) - p.ScalarBaseMult(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := nistec.NewP256Point().SetBytes(out); err != nil { - t.Fatal(err) - } - out = p.BytesCompressed() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } - }) - t.Run("P384", func(t *testing.T) { - if allocs := testing.AllocsPerRun(10, func() { - p := nistec.NewP384Point().SetGenerator() - scalar := make([]byte, 48) - rand.Read(scalar) - p.ScalarBaseMult(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := nistec.NewP384Point().SetBytes(out); err != nil { - t.Fatal(err) - } - out = p.BytesCompressed() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } - }) - t.Run("P521", func(t *testing.T) { - if allocs := testing.AllocsPerRun(10, func() { - p := nistec.NewP521Point().SetGenerator() - scalar := make([]byte, 66) - rand.Read(scalar) - p.ScalarBaseMult(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := nistec.NewP521Point().SetBytes(out); err != nil { - t.Fatal(err) - } - out = p.BytesCompressed() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } - }) -} - -type nistPoint[T any] interface { - Bytes() []byte - SetGenerator() T - SetBytes([]byte) (T, error) - Add(T, T) T - Double(T) T - ScalarMult(T, []byte) (T, error) - ScalarBaseMult([]byte) (T, error) -} - -func TestEquivalents(t *testing.T) { - t.Run("P224", func(t *testing.T) { - testEquivalents(t, nistec.NewP224Point, elliptic.P224()) - }) - t.Run("P256", func(t *testing.T) { - testEquivalents(t, nistec.NewP256Point, elliptic.P256()) - }) - t.Run("P384", func(t *testing.T) { - testEquivalents(t, nistec.NewP384Point, elliptic.P384()) - }) - t.Run("P521", func(t *testing.T) { - testEquivalents(t, nistec.NewP521Point, elliptic.P521()) - }) -} - -func testEquivalents[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic.Curve) { - p := newPoint().SetGenerator() - - elementSize := (c.Params().BitSize + 7) / 8 - two := make([]byte, elementSize) - two[len(two)-1] = 2 - nPlusTwo := make([]byte, elementSize) - new(big.Int).Add(c.Params().N, big.NewInt(2)).FillBytes(nPlusTwo) - - p1 := newPoint().Double(p) - p2 := newPoint().Add(p, p) - p3, err := newPoint().ScalarMult(p, two) - fatalIfErr(t, err) - p4, err := newPoint().ScalarBaseMult(two) - fatalIfErr(t, err) - p5, err := newPoint().ScalarMult(p, nPlusTwo) - fatalIfErr(t, err) - p6, err := newPoint().ScalarBaseMult(nPlusTwo) - fatalIfErr(t, err) - - if !bytes.Equal(p1.Bytes(), p2.Bytes()) { - t.Error("P+P != 2*P") - } - if !bytes.Equal(p1.Bytes(), p3.Bytes()) { - t.Error("P+P != [2]P") - } - if !bytes.Equal(p1.Bytes(), p4.Bytes()) { - t.Error("G+G != [2]G") - } - if !bytes.Equal(p1.Bytes(), p5.Bytes()) { - t.Error("P+P != [N+2]P") - } - if !bytes.Equal(p1.Bytes(), p6.Bytes()) { - t.Error("G+G != [N+2]G") - } -} - -func TestScalarMult(t *testing.T) { - t.Run("P224", func(t *testing.T) { - testScalarMult(t, nistec.NewP224Point, elliptic.P224()) - }) - t.Run("P256", func(t *testing.T) { - testScalarMult(t, nistec.NewP256Point, elliptic.P256()) - }) - t.Run("P384", func(t *testing.T) { - testScalarMult(t, nistec.NewP384Point, elliptic.P384()) - }) - t.Run("P521", func(t *testing.T) { - testScalarMult(t, nistec.NewP521Point, elliptic.P521()) - }) -} - -func testScalarMult[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic.Curve) { - G := newPoint().SetGenerator() - checkScalar := func(t *testing.T, scalar []byte) { - p1, err := newPoint().ScalarBaseMult(scalar) - fatalIfErr(t, err) - p2, err := newPoint().ScalarMult(G, scalar) - fatalIfErr(t, err) - if !bytes.Equal(p1.Bytes(), p2.Bytes()) { - t.Error("[k]G != ScalarBaseMult(k)") - } - - expectInfinity := new(big.Int).Mod(new(big.Int).SetBytes(scalar), c.Params().N).Sign() == 0 - if expectInfinity { - if !bytes.Equal(p1.Bytes(), newPoint().Bytes()) { - t.Error("ScalarBaseMult(k) != ∞") - } - if !bytes.Equal(p2.Bytes(), newPoint().Bytes()) { - t.Error("[k]G != ∞") - } - } else { - if bytes.Equal(p1.Bytes(), newPoint().Bytes()) { - t.Error("ScalarBaseMult(k) == ∞") - } - if bytes.Equal(p2.Bytes(), newPoint().Bytes()) { - t.Error("[k]G == ∞") - } - } - - d := new(big.Int).SetBytes(scalar) - d.Sub(c.Params().N, d) - d.Mod(d, c.Params().N) - g1, err := newPoint().ScalarBaseMult(d.FillBytes(make([]byte, len(scalar)))) - fatalIfErr(t, err) - g1.Add(g1, p1) - if !bytes.Equal(g1.Bytes(), newPoint().Bytes()) { - t.Error("[N - k]G + [k]G != ∞") - } - } - - byteLen := len(c.Params().N.Bytes()) - bitLen := c.Params().N.BitLen() - t.Run("0", func(t *testing.T) { checkScalar(t, make([]byte, byteLen)) }) - t.Run("1", func(t *testing.T) { - checkScalar(t, big.NewInt(1).FillBytes(make([]byte, byteLen))) - }) - t.Run("N-1", func(t *testing.T) { - checkScalar(t, new(big.Int).Sub(c.Params().N, big.NewInt(1)).Bytes()) - }) - t.Run("N", func(t *testing.T) { checkScalar(t, c.Params().N.Bytes()) }) - t.Run("N+1", func(t *testing.T) { - checkScalar(t, new(big.Int).Add(c.Params().N, big.NewInt(1)).Bytes()) - }) - t.Run("all1s", func(t *testing.T) { - s := new(big.Int).Lsh(big.NewInt(1), uint(bitLen)) - s.Sub(s, big.NewInt(1)) - checkScalar(t, s.Bytes()) - }) - if testing.Short() { - return - } - for i := 0; i < bitLen; i++ { - t.Run(fmt.Sprintf("1<<%d", i), func(t *testing.T) { - s := new(big.Int).Lsh(big.NewInt(1), uint(i)) - checkScalar(t, s.FillBytes(make([]byte, byteLen))) - }) - } - for i := 0; i <= 64; i++ { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - checkScalar(t, big.NewInt(int64(i)).FillBytes(make([]byte, byteLen))) - }) - } - // Test N-64...N+64 since they risk overlapping with precomputed table values - // in the final additions. - for i := int64(-64); i <= 64; i++ { - t.Run(fmt.Sprintf("N%+d", i), func(t *testing.T) { - checkScalar(t, new(big.Int).Add(c.Params().N, big.NewInt(i)).Bytes()) - }) - } -} - -func fatalIfErr(t *testing.T, err error) { - t.Helper() - if err != nil { - t.Fatal(err) - } -} - -func BenchmarkScalarMult(b *testing.B) { - b.Run("P224", func(b *testing.B) { - benchmarkScalarMult(b, nistec.NewP224Point().SetGenerator(), 28) - }) - b.Run("P256", func(b *testing.B) { - benchmarkScalarMult(b, nistec.NewP256Point().SetGenerator(), 32) - }) - b.Run("P384", func(b *testing.B) { - benchmarkScalarMult(b, nistec.NewP384Point().SetGenerator(), 48) - }) - b.Run("P521", func(b *testing.B) { - benchmarkScalarMult(b, nistec.NewP521Point().SetGenerator(), 66) - }) -} - -func benchmarkScalarMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) { - scalar := make([]byte, scalarSize) - rand.Read(scalar) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - p.ScalarMult(p, scalar) - } -} - -func BenchmarkScalarBaseMult(b *testing.B) { - b.Run("P224", func(b *testing.B) { - benchmarkScalarBaseMult(b, nistec.NewP224Point().SetGenerator(), 28) - }) - b.Run("P256", func(b *testing.B) { - benchmarkScalarBaseMult(b, nistec.NewP256Point().SetGenerator(), 32) - }) - b.Run("P384", func(b *testing.B) { - benchmarkScalarBaseMult(b, nistec.NewP384Point().SetGenerator(), 48) - }) - b.Run("P521", func(b *testing.B) { - benchmarkScalarBaseMult(b, nistec.NewP521Point().SetGenerator(), 66) - }) -} - -func benchmarkScalarBaseMult[P nistPoint[P]](b *testing.B, p P, scalarSize int) { - scalar := make([]byte, scalarSize) - rand.Read(scalar) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - p.ScalarBaseMult(scalar) - } -} diff --git a/crypto/internal/nistec/p256.go b/crypto/internal/nistec/p256.go deleted file mode 100644 index 392b494346b..00000000000 --- a/crypto/internal/nistec/p256.go +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by generate.go. DO NOT EDIT. - -//go:build (!amd64 && !arm64 && !ppc64le && !s390x) || purego - -package nistec - -import ( - "github.com/runZeroInc/excrypto/crypto/internal/nistec/fiat" - "github.com/runZeroInc/excrypto/crypto/subtle" - "errors" - "sync" -) - -// p256ElementLength is the length of an element of the base or scalar field, -// which have the same bytes length for all NIST P curves. -const p256ElementLength = 32 - -// P256Point is a P256 point. The zero value is NOT valid. -type P256Point struct { - // The point is represented in projective coordinates (X:Y:Z), - // where x = X/Z and y = Y/Z. - x, y, z *fiat.P256Element -} - -// NewP256Point returns a new P256Point representing the point at infinity point. -func NewP256Point() *P256Point { - return &P256Point{ - x: new(fiat.P256Element), - y: new(fiat.P256Element).One(), - z: new(fiat.P256Element), - } -} - -// SetGenerator sets p to the canonical generator and returns p. -func (p *P256Point) SetGenerator() *P256Point { - p.x.SetBytes([]byte{0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x3, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}) - p.y.SetBytes([]byte{0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0xf, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}) - p.z.One() - return p -} - -// Set sets p = q and returns p. -func (p *P256Point) Set(q *P256Point) *P256Point { - p.x.Set(q.x) - p.y.Set(q.y) - p.z.Set(q.z) - return p -} - -// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in -// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on -// the curve, it returns nil and an error, and the receiver is unchanged. -// Otherwise, it returns p. -func (p *P256Point) SetBytes(b []byte) (*P256Point, error) { - switch { - // Point at infinity. - case len(b) == 1 && b[0] == 0: - return p.Set(NewP256Point()), nil - - // Uncompressed form. - case len(b) == 1+2*p256ElementLength && b[0] == 4: - x, err := new(fiat.P256Element).SetBytes(b[1 : 1+p256ElementLength]) - if err != nil { - return nil, err - } - y, err := new(fiat.P256Element).SetBytes(b[1+p256ElementLength:]) - if err != nil { - return nil, err - } - if err := p256CheckOnCurve(x, y); err != nil { - return nil, err - } - p.x.Set(x) - p.y.Set(y) - p.z.One() - return p, nil - - // Compressed form. - case len(b) == 1+p256ElementLength && (b[0] == 2 || b[0] == 3): - x, err := new(fiat.P256Element).SetBytes(b[1:]) - if err != nil { - return nil, err - } - - // y² = x³ - 3x + b - y := p256Polynomial(new(fiat.P256Element), x) - if !p256Sqrt(y, y) { - return nil, errors.New("invalid P256 compressed point encoding") - } - - // Select the positive or negative root, as indicated by the least - // significant bit, based on the encoding type byte. - otherRoot := new(fiat.P256Element) - otherRoot.Sub(otherRoot, y) - cond := y.Bytes()[p256ElementLength-1]&1 ^ b[0]&1 - y.Select(otherRoot, y, int(cond)) - - p.x.Set(x) - p.y.Set(y) - p.z.One() - return p, nil - - default: - return nil, errors.New("invalid P256 point encoding") - } -} - -var _p256B *fiat.P256Element -var _p256BOnce sync.Once - -func p256B() *fiat.P256Element { - _p256BOnce.Do(func() { - _p256B, _ = new(fiat.P256Element).SetBytes([]byte{0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x6, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}) - }) - return _p256B -} - -// p256Polynomial sets y2 to x³ - 3x + b, and returns y2. -func p256Polynomial(y2, x *fiat.P256Element) *fiat.P256Element { - y2.Square(x) - y2.Mul(y2, x) - - threeX := new(fiat.P256Element).Add(x, x) - threeX.Add(threeX, x) - y2.Sub(y2, threeX) - - return y2.Add(y2, p256B()) -} - -func p256CheckOnCurve(x, y *fiat.P256Element) error { - // y² = x³ - 3x + b - rhs := p256Polynomial(new(fiat.P256Element), x) - lhs := new(fiat.P256Element).Square(y) - if rhs.Equal(lhs) != 1 { - return errors.New("P256 point not on curve") - } - return nil -} - -// Bytes returns the uncompressed or infinity encoding of p, as specified in -// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at -// infinity is shorter than all other encodings. -func (p *P256Point) Bytes() []byte { - // This function is outlined to make the allocations inline in the caller - // rather than happen on the heap. - var out [1 + 2*p256ElementLength]byte - return p.bytes(&out) -} - -func (p *P256Point) bytes(out *[1 + 2*p256ElementLength]byte) []byte { - if p.z.IsZero() == 1 { - return append(out[:0], 0) - } - - zinv := new(fiat.P256Element).Invert(p.z) - x := new(fiat.P256Element).Mul(p.x, zinv) - y := new(fiat.P256Element).Mul(p.y, zinv) - - buf := append(out[:0], 4) - buf = append(buf, x.Bytes()...) - buf = append(buf, y.Bytes()...) - return buf -} - -// BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1, -// Version 2.0, Section 2.3.5, or an error if p is the point at infinity. -func (p *P256Point) BytesX() ([]byte, error) { - // This function is outlined to make the allocations inline in the caller - // rather than happen on the heap. - var out [p256ElementLength]byte - return p.bytesX(&out) -} - -func (p *P256Point) bytesX(out *[p256ElementLength]byte) ([]byte, error) { - if p.z.IsZero() == 1 { - return nil, errors.New("P256 point is the point at infinity") - } - - zinv := new(fiat.P256Element).Invert(p.z) - x := new(fiat.P256Element).Mul(p.x, zinv) - - return append(out[:0], x.Bytes()...), nil -} - -// BytesCompressed returns the compressed or infinity encoding of p, as -// specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the -// point at infinity is shorter than all other encodings. -func (p *P256Point) BytesCompressed() []byte { - // This function is outlined to make the allocations inline in the caller - // rather than happen on the heap. - var out [1 + p256ElementLength]byte - return p.bytesCompressed(&out) -} - -func (p *P256Point) bytesCompressed(out *[1 + p256ElementLength]byte) []byte { - if p.z.IsZero() == 1 { - return append(out[:0], 0) - } - - zinv := new(fiat.P256Element).Invert(p.z) - x := new(fiat.P256Element).Mul(p.x, zinv) - y := new(fiat.P256Element).Mul(p.y, zinv) - - // Encode the sign of the y coordinate (indicated by the least significant - // bit) as the encoding type (2 or 3). - buf := append(out[:0], 2) - buf[0] |= y.Bytes()[p256ElementLength-1] & 1 - buf = append(buf, x.Bytes()...) - return buf -} - -// Add sets q = p1 + p2, and returns q. The points may overlap. -func (q *P256Point) Add(p1, p2 *P256Point) *P256Point { - // Complete addition formula for a = -3 from "Complete addition formulas for - // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. - - t0 := new(fiat.P256Element).Mul(p1.x, p2.x) // t0 := X1 * X2 - t1 := new(fiat.P256Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 - t2 := new(fiat.P256Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 - t3 := new(fiat.P256Element).Add(p1.x, p1.y) // t3 := X1 + Y1 - t4 := new(fiat.P256Element).Add(p2.x, p2.y) // t4 := X2 + Y2 - t3.Mul(t3, t4) // t3 := t3 * t4 - t4.Add(t0, t1) // t4 := t0 + t1 - t3.Sub(t3, t4) // t3 := t3 - t4 - t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 - x3 := new(fiat.P256Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 - t4.Mul(t4, x3) // t4 := t4 * X3 - x3.Add(t1, t2) // X3 := t1 + t2 - t4.Sub(t4, x3) // t4 := t4 - X3 - x3.Add(p1.x, p1.z) // X3 := X1 + Z1 - y3 := new(fiat.P256Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 - x3.Mul(x3, y3) // X3 := X3 * Y3 - y3.Add(t0, t2) // Y3 := t0 + t2 - y3.Sub(x3, y3) // Y3 := X3 - Y3 - z3 := new(fiat.P256Element).Mul(p256B(), t2) // Z3 := b * t2 - x3.Sub(y3, z3) // X3 := Y3 - Z3 - z3.Add(x3, x3) // Z3 := X3 + X3 - x3.Add(x3, z3) // X3 := X3 + Z3 - z3.Sub(t1, x3) // Z3 := t1 - X3 - x3.Add(t1, x3) // X3 := t1 + X3 - y3.Mul(p256B(), y3) // Y3 := b * Y3 - t1.Add(t2, t2) // t1 := t2 + t2 - t2.Add(t1, t2) // t2 := t1 + t2 - y3.Sub(y3, t2) // Y3 := Y3 - t2 - y3.Sub(y3, t0) // Y3 := Y3 - t0 - t1.Add(y3, y3) // t1 := Y3 + Y3 - y3.Add(t1, y3) // Y3 := t1 + Y3 - t1.Add(t0, t0) // t1 := t0 + t0 - t0.Add(t1, t0) // t0 := t1 + t0 - t0.Sub(t0, t2) // t0 := t0 - t2 - t1.Mul(t4, y3) // t1 := t4 * Y3 - t2.Mul(t0, y3) // t2 := t0 * Y3 - y3.Mul(x3, z3) // Y3 := X3 * Z3 - y3.Add(y3, t2) // Y3 := Y3 + t2 - x3.Mul(t3, x3) // X3 := t3 * X3 - x3.Sub(x3, t1) // X3 := X3 - t1 - z3.Mul(t4, z3) // Z3 := t4 * Z3 - t1.Mul(t3, t0) // t1 := t3 * t0 - z3.Add(z3, t1) // Z3 := Z3 + t1 - - q.x.Set(x3) - q.y.Set(y3) - q.z.Set(z3) - return q -} - -// Double sets q = p + p, and returns q. The points may overlap. -func (q *P256Point) Double(p *P256Point) *P256Point { - // Complete addition formula for a = -3 from "Complete addition formulas for - // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. - - t0 := new(fiat.P256Element).Square(p.x) // t0 := X ^ 2 - t1 := new(fiat.P256Element).Square(p.y) // t1 := Y ^ 2 - t2 := new(fiat.P256Element).Square(p.z) // t2 := Z ^ 2 - t3 := new(fiat.P256Element).Mul(p.x, p.y) // t3 := X * Y - t3.Add(t3, t3) // t3 := t3 + t3 - z3 := new(fiat.P256Element).Mul(p.x, p.z) // Z3 := X * Z - z3.Add(z3, z3) // Z3 := Z3 + Z3 - y3 := new(fiat.P256Element).Mul(p256B(), t2) // Y3 := b * t2 - y3.Sub(y3, z3) // Y3 := Y3 - Z3 - x3 := new(fiat.P256Element).Add(y3, y3) // X3 := Y3 + Y3 - y3.Add(x3, y3) // Y3 := X3 + Y3 - x3.Sub(t1, y3) // X3 := t1 - Y3 - y3.Add(t1, y3) // Y3 := t1 + Y3 - y3.Mul(x3, y3) // Y3 := X3 * Y3 - x3.Mul(x3, t3) // X3 := X3 * t3 - t3.Add(t2, t2) // t3 := t2 + t2 - t2.Add(t2, t3) // t2 := t2 + t3 - z3.Mul(p256B(), z3) // Z3 := b * Z3 - z3.Sub(z3, t2) // Z3 := Z3 - t2 - z3.Sub(z3, t0) // Z3 := Z3 - t0 - t3.Add(z3, z3) // t3 := Z3 + Z3 - z3.Add(z3, t3) // Z3 := Z3 + t3 - t3.Add(t0, t0) // t3 := t0 + t0 - t0.Add(t3, t0) // t0 := t3 + t0 - t0.Sub(t0, t2) // t0 := t0 - t2 - t0.Mul(t0, z3) // t0 := t0 * Z3 - y3.Add(y3, t0) // Y3 := Y3 + t0 - t0.Mul(p.y, p.z) // t0 := Y * Z - t0.Add(t0, t0) // t0 := t0 + t0 - z3.Mul(t0, z3) // Z3 := t0 * Z3 - x3.Sub(x3, z3) // X3 := X3 - Z3 - z3.Mul(t0, t1) // Z3 := t0 * t1 - z3.Add(z3, z3) // Z3 := Z3 + Z3 - z3.Add(z3, z3) // Z3 := Z3 + Z3 - - q.x.Set(x3) - q.y.Set(y3) - q.z.Set(z3) - return q -} - -// Select sets q to p1 if cond == 1, and to p2 if cond == 0. -func (q *P256Point) Select(p1, p2 *P256Point, cond int) *P256Point { - q.x.Select(p1.x, p2.x, cond) - q.y.Select(p1.y, p2.y, cond) - q.z.Select(p1.z, p2.z, cond) - return q -} - -// A p256Table holds the first 15 multiples of a point at offset -1, so [1]P -// is at table[0], [15]P is at table[14], and [0]P is implicitly the identity -// point. -type p256Table [15]*P256Point - -// Select selects the n-th multiple of the table base point into p. It works in -// constant time by iterating over every entry of the table. n must be in [0, 15]. -func (table *p256Table) Select(p *P256Point, n uint8) { - if n >= 16 { - panic("nistec: internal error: p256Table called with out-of-bounds value") - } - p.Set(NewP256Point()) - for i := uint8(1); i < 16; i++ { - cond := subtle.ConstantTimeByteEq(i, n) - p.Select(table[i-1], p, cond) - } -} - -// ScalarMult sets p = scalar * q, and returns p. -func (p *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) { - // Compute a p256Table for the base point q. The explicit NewP256Point - // calls get inlined, letting the allocations live on the stack. - var table = p256Table{NewP256Point(), NewP256Point(), NewP256Point(), - NewP256Point(), NewP256Point(), NewP256Point(), NewP256Point(), - NewP256Point(), NewP256Point(), NewP256Point(), NewP256Point(), - NewP256Point(), NewP256Point(), NewP256Point(), NewP256Point()} - table[0].Set(q) - for i := 1; i < 15; i += 2 { - table[i].Double(table[i/2]) - table[i+1].Add(table[i], q) - } - - // Instead of doing the classic double-and-add chain, we do it with a - // four-bit window: we double four times, and then add [0-15]P. - t := NewP256Point() - p.Set(NewP256Point()) - for i, byte := range scalar { - // No need to double on the first iteration, as p is the identity at - // this point, and [N]∞ = ∞. - if i != 0 { - p.Double(p) - p.Double(p) - p.Double(p) - p.Double(p) - } - - windowValue := byte >> 4 - table.Select(t, windowValue) - p.Add(p, t) - - p.Double(p) - p.Double(p) - p.Double(p) - p.Double(p) - - windowValue = byte & 0b1111 - table.Select(t, windowValue) - p.Add(p, t) - } - - return p, nil -} - -var p256GeneratorTable *[p256ElementLength * 2]p256Table -var p256GeneratorTableOnce sync.Once - -// generatorTable returns a sequence of p256Tables. The first table contains -// multiples of G. Each successive table is the previous table doubled four -// times. -func (p *P256Point) generatorTable() *[p256ElementLength * 2]p256Table { - p256GeneratorTableOnce.Do(func() { - p256GeneratorTable = new([p256ElementLength * 2]p256Table) - base := NewP256Point().SetGenerator() - for i := 0; i < p256ElementLength*2; i++ { - p256GeneratorTable[i][0] = NewP256Point().Set(base) - for j := 1; j < 15; j++ { - p256GeneratorTable[i][j] = NewP256Point().Add(p256GeneratorTable[i][j-1], base) - } - base.Double(base) - base.Double(base) - base.Double(base) - base.Double(base) - } - }) - return p256GeneratorTable -} - -// ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and -// returns p. -func (p *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) { - if len(scalar) != p256ElementLength { - return nil, errors.New("invalid scalar length") - } - tables := p.generatorTable() - - // This is also a scalar multiplication with a four-bit window like in - // ScalarMult, but in this case the doublings are precomputed. The value - // [windowValue]G added at iteration k would normally get doubled - // (totIterations-k)×4 times, but with a larger precomputation we can - // instead add [2^((totIterations-k)×4)][windowValue]G and avoid the - // doublings between iterations. - t := NewP256Point() - p.Set(NewP256Point()) - tableIndex := len(tables) - 1 - for _, byte := range scalar { - windowValue := byte >> 4 - tables[tableIndex].Select(t, windowValue) - p.Add(p, t) - tableIndex-- - - windowValue = byte & 0b1111 - tables[tableIndex].Select(t, windowValue) - p.Add(p, t) - tableIndex-- - } - - return p, nil -} - -// p256Sqrt sets e to a square root of x. If x is not a square, p256Sqrt returns -// false and e is unchanged. e and x can overlap. -func p256Sqrt(e, x *fiat.P256Element) (isSquare bool) { - candidate := new(fiat.P256Element) - p256SqrtCandidate(candidate, x) - square := new(fiat.P256Element).Square(candidate) - if square.Equal(x) != 1 { - return false - } - e.Set(candidate) - return true -} - -// p256SqrtCandidate sets z to a square root candidate for x. z and x must not overlap. -func p256SqrtCandidate(z, x *fiat.P256Element) { - // Since p = 3 mod 4, exponentiation by (p + 1) / 4 yields a square root candidate. - // - // The sequence of 7 multiplications and 253 squarings is derived from the - // following addition chain generated with github.com/mmcloughlin/addchain v0.4.0. - // - // _10 = 2*1 - // _11 = 1 + _10 - // _1100 = _11 << 2 - // _1111 = _11 + _1100 - // _11110000 = _1111 << 4 - // _11111111 = _1111 + _11110000 - // x16 = _11111111 << 8 + _11111111 - // x32 = x16 << 16 + x16 - // return ((x32 << 32 + 1) << 96 + 1) << 94 - // - var t0 = new(fiat.P256Element) - - z.Square(x) - z.Mul(x, z) - t0.Square(z) - for s := 1; s < 2; s++ { - t0.Square(t0) - } - z.Mul(z, t0) - t0.Square(z) - for s := 1; s < 4; s++ { - t0.Square(t0) - } - z.Mul(z, t0) - t0.Square(z) - for s := 1; s < 8; s++ { - t0.Square(t0) - } - z.Mul(z, t0) - t0.Square(z) - for s := 1; s < 16; s++ { - t0.Square(t0) - } - z.Mul(z, t0) - for s := 0; s < 32; s++ { - z.Square(z) - } - z.Mul(x, z) - for s := 0; s < 96; s++ { - z.Square(z) - } - z.Mul(x, z) - for s := 0; s < 94; s++ { - z.Square(z) - } -} diff --git a/crypto/internal/nistec/p256_asm_table.bin b/crypto/internal/nistec/p256_asm_table.bin deleted file mode 100644 index 20c527e4e0e..00000000000 Binary files a/crypto/internal/nistec/p256_asm_table.bin and /dev/null differ diff --git a/crypto/internal/nistec/p256_ordinv_test.go b/crypto/internal/nistec/p256_ordinv_test.go deleted file mode 100644 index 0be5a888bba..00000000000 --- a/crypto/internal/nistec/p256_ordinv_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (amd64 || arm64) && !purego - -package nistec_test - -import ( - "bytes" - "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/crypto/internal/nistec" - "math/big" - "testing" -) - -func TestP256OrdInverse(t *testing.T) { - N := elliptic.P256().Params().N - - // inv(0) is expected to be 0. - zero := make([]byte, 32) - out, err := nistec.P256OrdInverse(zero) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, zero) { - t.Error("unexpected output for inv(0)") - } - - // inv(N) is also 0 mod N. - input := make([]byte, 32) - N.FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, zero) { - t.Error("unexpected output for inv(N)") - } - if !bytes.Equal(input, N.Bytes()) { - t.Error("input was modified") - } - - // Check inv(1) and inv(N+1) against math/big - exp := new(big.Int).ModInverse(big.NewInt(1), N).FillBytes(make([]byte, 32)) - big.NewInt(1).FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, exp) { - t.Error("unexpected output for inv(1)") - } - new(big.Int).Add(N, big.NewInt(1)).FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, exp) { - t.Error("unexpected output for inv(N+1)") - } - - // Check inv(20) and inv(N+20) against math/big - exp = new(big.Int).ModInverse(big.NewInt(20), N).FillBytes(make([]byte, 32)) - big.NewInt(20).FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, exp) { - t.Error("unexpected output for inv(20)") - } - new(big.Int).Add(N, big.NewInt(20)).FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, exp) { - t.Error("unexpected output for inv(N+20)") - } - - // Check inv(2^256-1) against math/big - bigInput := new(big.Int).Lsh(big.NewInt(1), 256) - bigInput.Sub(bigInput, big.NewInt(1)) - exp = new(big.Int).ModInverse(bigInput, N).FillBytes(make([]byte, 32)) - bigInput.FillBytes(input) - out, err = nistec.P256OrdInverse(input) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(out, exp) { - t.Error("unexpected output for inv(2^256-1)") - } -} diff --git a/crypto/issue21104_test.go b/crypto/issue21104_test.go index 50f874d4d6a..8ed1c53196f 100644 --- a/crypto/issue21104_test.go +++ b/crypto/issue21104_test.go @@ -5,10 +5,11 @@ package crypto_test import ( + "testing" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/rc4" - "testing" ) func TestRC4OutOfBoundsWrite(t *testing.T) { diff --git a/crypto/md5/_asm/go.mod b/crypto/md5/_asm/go.mod index e69de29bb2d..db1e46d8eee 100644 --- a/crypto/md5/_asm/go.mod +++ b/crypto/md5/_asm/go.mod @@ -0,0 +1,11 @@ +module crypto/md5/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/md5/_asm/go.sum b/crypto/md5/_asm/go.sum index e69de29bb2d..76af484b2eb 100644 --- a/crypto/md5/_asm/go.sum +++ b/crypto/md5/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/md5/example_test.go b/crypto/md5/example_test.go index 6331f81ded6..fbedad7d374 100644 --- a/crypto/md5/example_test.go +++ b/crypto/md5/example_test.go @@ -6,10 +6,11 @@ package md5_test import ( "fmt" - "github.com/runZeroInc/excrypto/crypto/md5" "io" "log" "os" + + "github.com/runZeroInc/excrypto/crypto/md5" ) func ExampleNew() { diff --git a/crypto/md5/gen.go b/crypto/md5/gen.go index 438b6e9bafd..f4f76cb3bc2 100644 --- a/crypto/md5/gen.go +++ b/crypto/md5/gen.go @@ -219,7 +219,7 @@ func blockGeneric(dig *digest, p []byte) { // load input block {{range $i := seq 16 -}} - {{printf "x%x := byteorder.LeUint32(q[4*%#x:])" $i $i}} + {{printf "x%x := byteorder.LEUint32(q[4*%#x:])" $i $i}} {{end}} // round 1 diff --git a/crypto/md5/md5.go b/crypto/md5/md5.go index dece44d68e1..f454b066d31 100644 --- a/crypto/md5/md5.go +++ b/crypto/md5/md5.go @@ -12,9 +12,12 @@ package md5 import ( "errors" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/internal/byteorder" ) @@ -28,6 +31,11 @@ const Size = 16 // The blocksize of MD5 in bytes. const BlockSize = 64 +// The maximum number of bytes that can be passed to block(). The limit exists +// because implementations that rely on assembly routines are not preemptible. +const maxAsmIters = 1024 +const maxAsmSize = BlockSize * maxAsmIters // 64KiB + const ( init0 = 0x67452301 init1 = 0xEFCDAB89 @@ -63,13 +71,13 @@ func (d *digest) MarshalBinary() ([]byte, error) { func (d *digest) AppendBinary(b []byte) ([]byte, error) { b = append(b, magic...) - b = byteorder.BeAppendUint32(b, d.s[0]) - b = byteorder.BeAppendUint32(b, d.s[1]) - b = byteorder.BeAppendUint32(b, d.s[2]) - b = byteorder.BeAppendUint32(b, d.s[3]) + b = byteorder.BEAppendUint32(b, d.s[0]) + b = byteorder.BEAppendUint32(b, d.s[1]) + b = byteorder.BEAppendUint32(b, d.s[2]) + b = byteorder.BEAppendUint32(b, d.s[3]) b = append(b, d.x[:d.nx]...) b = append(b, make([]byte, len(d.x)-d.nx)...) - b = byteorder.BeAppendUint64(b, d.len) + b = byteorder.BEAppendUint64(b, d.len) return b, nil } @@ -92,15 +100,20 @@ func (d *digest) UnmarshalBinary(b []byte) error { } func consumeUint64(b []byte) ([]byte, uint64) { - return b[8:], byteorder.BeUint64(b[0:8]) + return b[8:], byteorder.BEUint64(b[0:8]) } func consumeUint32(b []byte) ([]byte, uint32) { - return b[4:], byteorder.BeUint32(b[0:4]) + return b[4:], byteorder.BEUint32(b[0:4]) +} + +func (d *digest) Clone() (hash.Cloner, error) { + r := *d + return &r, nil } // New returns a new [hash.Hash] computing the MD5 checksum. The Hash -// also implements [encoding.BinaryMarshaler], [encoding.AppendBinary] and +// also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. func New() hash.Hash { @@ -114,6 +127,9 @@ func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Write(p []byte) (nn int, err error) { + if fips140only.Enabled { + return 0, errors.New("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") + } // Note that we currently call block or blockGeneric // directly (guarded using haveAsm) because this allows // escape analysis to see that p and d don't escape. @@ -135,6 +151,11 @@ func (d *digest) Write(p []byte) (nn int, err error) { if len(p) >= BlockSize { n := len(p) &^ (BlockSize - 1) if haveAsm { + for n > maxAsmSize { + block(d, p[:maxAsmSize]) + p = p[maxAsmSize:] + n -= maxAsmSize + } block(d, p[:n]) } else { blockGeneric(d, p[:n]) @@ -155,6 +176,10 @@ func (d *digest) Sum(in []byte) []byte { } func (d *digest) checkSum() [Size]byte { + if fips140only.Enabled { + panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") + } + // Append 0x80 to the end of the message and then append zeros // until the length is a multiple of 56 bytes. Finally append // 8 bytes representing the message length in bits. @@ -162,7 +187,7 @@ func (d *digest) checkSum() [Size]byte { // 1 byte end marker :: 0-63 padding bytes :: 8 byte length tmp := [1 + 63 + 8]byte{0x80} pad := (55 - d.len) % 64 // calculate number of padding bytes - byteorder.LePutUint64(tmp[1+pad:], d.len<<3) // append length in bits + byteorder.LEPutUint64(tmp[1+pad:], d.len<<3) // append length in bits d.Write(tmp[:1+pad+8]) // The previous write ensures that a whole number of @@ -172,10 +197,10 @@ func (d *digest) checkSum() [Size]byte { } var digest [Size]byte - byteorder.LePutUint32(digest[0:], d.s[0]) - byteorder.LePutUint32(digest[4:], d.s[1]) - byteorder.LePutUint32(digest[8:], d.s[2]) - byteorder.LePutUint32(digest[12:], d.s[3]) + byteorder.LEPutUint32(digest[0:], d.s[0]) + byteorder.LEPutUint32(digest[4:], d.s[1]) + byteorder.LEPutUint32(digest[8:], d.s[2]) + byteorder.LEPutUint32(digest[12:], d.s[3]) return digest } diff --git a/crypto/md5/md5_test.go b/crypto/md5/md5_test.go index c2dcc3a0eab..8c992c26e4a 100644 --- a/crypto/md5/md5_test.go +++ b/crypto/md5/md5_test.go @@ -7,11 +7,12 @@ package md5 import ( "bytes" "fmt" - "hash" "io" "testing" "unsafe" + "github.com/runZeroInc/excrypto/hash" + "crypto/rand" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" @@ -135,10 +136,11 @@ func TestGoldenMarshal(t *testing.T) { func TestLarge(t *testing.T) { const N = 10000 + const offsets = 4 ok := "2bb571599a4180e1d542f76904adc3df" // md5sum of "0123456789" * 1000 - block := make([]byte, 10004) + block := make([]byte, N+offsets) c := New() - for offset := 0; offset < 4; offset++ { + for offset := 0; offset < offsets; offset++ { for i := 0; i < N; i++ { block[offset+i] = '0' + byte(i%10) } @@ -157,6 +159,31 @@ func TestLarge(t *testing.T) { } } +func TestExtraLarge(t *testing.T) { + const N = 100000 + const offsets = 4 + ok := "13572e9e296cff52b79c52148313c3a5" // md5sum of "0123456789" * 10000 + block := make([]byte, N+offsets) + c := New() + for offset := 0; offset < offsets; offset++ { + for i := 0; i < N; i++ { + block[offset+i] = '0' + byte(i%10) + } + for blockSize := 10; blockSize <= N; blockSize *= 10 { + blocks := N / blockSize + b := block[offset : offset+blockSize] + c.Reset() + for i := 0; i < blocks; i++ { + c.Write(b) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != ok { + t.Fatalf("md5 TestExtraLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok) + } + } + } +} + // Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. func TestBlockGeneric(t *testing.T) { gen, asm := New().(*digest), New().(*digest) @@ -227,6 +254,7 @@ func TestLargeHashes(t *testing.T) { } func TestAllocations(t *testing.T) { + cryptotest.SkipTestAllocations(t) in := []byte("hello, world!") out := make([]byte, 0, Size) h := New() @@ -244,6 +272,18 @@ func TestMD5Hash(t *testing.T) { cryptotest.TestHash(t, New) } +func TestExtraMethods(t *testing.T) { + h := maybeCloner(New()) + cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") +} + +func maybeCloner(h hash.Hash) any { + if c, ok := h.(hash.Cloner); ok { + return &c + } + return &h +} + var bench = New() var buf = make([]byte, 1024*1024*8+1) var sum = make([]byte, bench.Size()) diff --git a/crypto/md5/md5block.go b/crypto/md5/md5block.go index 274b430b2af..0b2fd0cfab8 100644 --- a/crypto/md5/md5block.go +++ b/crypto/md5/md5block.go @@ -7,8 +7,9 @@ package md5 import ( - "github.com/runZeroInc/excrypto/internal/byteorder" "math/bits" + + "github.com/runZeroInc/excrypto/internal/byteorder" ) func blockGeneric(dig *digest, p []byte) { @@ -24,22 +25,22 @@ func blockGeneric(dig *digest, p []byte) { aa, bb, cc, dd := a, b, c, d // load input block - x0 := byteorder.LeUint32(q[4*0x0:]) - x1 := byteorder.LeUint32(q[4*0x1:]) - x2 := byteorder.LeUint32(q[4*0x2:]) - x3 := byteorder.LeUint32(q[4*0x3:]) - x4 := byteorder.LeUint32(q[4*0x4:]) - x5 := byteorder.LeUint32(q[4*0x5:]) - x6 := byteorder.LeUint32(q[4*0x6:]) - x7 := byteorder.LeUint32(q[4*0x7:]) - x8 := byteorder.LeUint32(q[4*0x8:]) - x9 := byteorder.LeUint32(q[4*0x9:]) - xa := byteorder.LeUint32(q[4*0xa:]) - xb := byteorder.LeUint32(q[4*0xb:]) - xc := byteorder.LeUint32(q[4*0xc:]) - xd := byteorder.LeUint32(q[4*0xd:]) - xe := byteorder.LeUint32(q[4*0xe:]) - xf := byteorder.LeUint32(q[4*0xf:]) + x0 := byteorder.LEUint32(q[4*0x0:]) + x1 := byteorder.LEUint32(q[4*0x1:]) + x2 := byteorder.LEUint32(q[4*0x2:]) + x3 := byteorder.LEUint32(q[4*0x3:]) + x4 := byteorder.LEUint32(q[4*0x4:]) + x5 := byteorder.LEUint32(q[4*0x5:]) + x6 := byteorder.LEUint32(q[4*0x6:]) + x7 := byteorder.LEUint32(q[4*0x7:]) + x8 := byteorder.LEUint32(q[4*0x8:]) + x9 := byteorder.LEUint32(q[4*0x9:]) + xa := byteorder.LEUint32(q[4*0xa:]) + xb := byteorder.LEUint32(q[4*0xb:]) + xc := byteorder.LEUint32(q[4*0xc:]) + xd := byteorder.LEUint32(q[4*0xd:]) + xe := byteorder.LEUint32(q[4*0xe:]) + xf := byteorder.LEUint32(q[4*0xf:]) // round 1 a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x0+0xd76aa478, 7) diff --git a/crypto/mlkem/example_test.go b/crypto/mlkem/example_test.go new file mode 100644 index 00000000000..a8451696c13 --- /dev/null +++ b/crypto/mlkem/example_test.go @@ -0,0 +1,48 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mlkem_test + +import ( + "log" + + "github.com/runZeroInc/excrypto/crypto/mlkem" +) + +func Example() { + // Alice generates a new key pair and sends the encapsulation key to Bob. + dk, err := mlkem.GenerateKey768() + if err != nil { + log.Fatal(err) + } + encapsulationKey := dk.EncapsulationKey().Bytes() + + // Bob uses the encapsulation key to encapsulate a shared secret, and sends + // back the ciphertext to Alice. + ciphertext := Bob(encapsulationKey) + + // Alice decapsulates the shared secret from the ciphertext. + sharedSecret, err := dk.Decapsulate(ciphertext) + if err != nil { + log.Fatal(err) + } + + // Alice and Bob now share a secret. + _ = sharedSecret +} + +func Bob(encapsulationKey []byte) (ciphertext []byte) { + // Bob encapsulates a shared secret using the encapsulation key. + ek, err := mlkem.NewEncapsulationKey768(encapsulationKey) + if err != nil { + log.Fatal(err) + } + sharedSecret, ciphertext := ek.Encapsulate() + + // Alice and Bob now share a secret. + _ = sharedSecret + + // Bob sends the ciphertext to Alice. + return ciphertext +} diff --git a/crypto/mlkem/mlkem.go b/crypto/mlkem/mlkem.go new file mode 100644 index 00000000000..fc24801e238 --- /dev/null +++ b/crypto/mlkem/mlkem.go @@ -0,0 +1,192 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mlkem implements the quantum-resistant key encapsulation method +// ML-KEM (formerly known as Kyber), as specified in [NIST FIPS 203]. +// +// Most applications should use the ML-KEM-768 parameter set, as implemented by +// [DecapsulationKey768] and [EncapsulationKey768]. +// +// [NIST FIPS 203]: https://doi.org/10.6028/NIST.FIPS.203 +package mlkem + +import "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + +const ( + // SharedKeySize is the size of a shared key produced by ML-KEM. + SharedKeySize = 32 + + // SeedSize is the size of a seed used to generate a decapsulation key. + SeedSize = 64 + + // CiphertextSize768 is the size of a ciphertext produced by ML-KEM-768. + CiphertextSize768 = 1088 + + // EncapsulationKeySize768 is the size of an ML-KEM-768 encapsulation key. + EncapsulationKeySize768 = 1184 + + // CiphertextSize1024 is the size of a ciphertext produced by ML-KEM-1024. + CiphertextSize1024 = 1568 + + // EncapsulationKeySize1024 is the size of an ML-KEM-1024 encapsulation key. + EncapsulationKeySize1024 = 1568 +) + +// DecapsulationKey768 is the secret key used to decapsulate a shared key +// from a ciphertext. It includes various precomputed values. +type DecapsulationKey768 struct { + key *mlkem.DecapsulationKey768 +} + +// GenerateKey768 generates a new decapsulation key, drawing random bytes from +// the default crypto/rand source. The decapsulation key must be kept secret. +func GenerateKey768() (*DecapsulationKey768, error) { + key, err := mlkem.GenerateKey768() + if err != nil { + return nil, err + } + + return &DecapsulationKey768{key}, nil +} + +// NewDecapsulationKey768 expands a decapsulation key from a 64-byte seed in the +// "d || z" form. The seed must be uniformly random. +func NewDecapsulationKey768(seed []byte) (*DecapsulationKey768, error) { + key, err := mlkem.NewDecapsulationKey768(seed) + if err != nil { + return nil, err + } + + return &DecapsulationKey768{key}, nil +} + +// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form. +// +// The decapsulation key must be kept secret. +func (dk *DecapsulationKey768) Bytes() []byte { + return dk.key.Bytes() +} + +// Decapsulate generates a shared key from a ciphertext and a decapsulation +// key. If the ciphertext is not valid, Decapsulate returns an error. +// +// The shared key must be kept secret. +func (dk *DecapsulationKey768) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) { + return dk.key.Decapsulate(ciphertext) +} + +// EncapsulationKey returns the public encapsulation key necessary to produce +// ciphertexts. +func (dk *DecapsulationKey768) EncapsulationKey() *EncapsulationKey768 { + return &EncapsulationKey768{dk.key.EncapsulationKey()} +} + +// An EncapsulationKey768 is the public key used to produce ciphertexts to be +// decapsulated by the corresponding DecapsulationKey768. +type EncapsulationKey768 struct { + key *mlkem.EncapsulationKey768 +} + +// NewEncapsulationKey768 parses an encapsulation key from its encoded form. If +// the encapsulation key is not valid, NewEncapsulationKey768 returns an error. +func NewEncapsulationKey768(encapsulationKey []byte) (*EncapsulationKey768, error) { + key, err := mlkem.NewEncapsulationKey768(encapsulationKey) + if err != nil { + return nil, err + } + + return &EncapsulationKey768{key}, nil +} + +// Bytes returns the encapsulation key as a byte slice. +func (ek *EncapsulationKey768) Bytes() []byte { + return ek.key.Bytes() +} + +// Encapsulate generates a shared key and an associated ciphertext from an +// encapsulation key, drawing random bytes from the default crypto/rand source. +// +// The shared key must be kept secret. +func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { + return ek.key.Encapsulate() +} + +// DecapsulationKey1024 is the secret key used to decapsulate a shared key +// from a ciphertext. It includes various precomputed values. +type DecapsulationKey1024 struct { + key *mlkem.DecapsulationKey1024 +} + +// GenerateKey1024 generates a new decapsulation key, drawing random bytes from +// the default crypto/rand source. The decapsulation key must be kept secret. +func GenerateKey1024() (*DecapsulationKey1024, error) { + key, err := mlkem.GenerateKey1024() + if err != nil { + return nil, err + } + + return &DecapsulationKey1024{key}, nil +} + +// NewDecapsulationKey1024 expands a decapsulation key from a 64-byte seed in the +// "d || z" form. The seed must be uniformly random. +func NewDecapsulationKey1024(seed []byte) (*DecapsulationKey1024, error) { + key, err := mlkem.NewDecapsulationKey1024(seed) + if err != nil { + return nil, err + } + + return &DecapsulationKey1024{key}, nil +} + +// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form. +// +// The decapsulation key must be kept secret. +func (dk *DecapsulationKey1024) Bytes() []byte { + return dk.key.Bytes() +} + +// Decapsulate generates a shared key from a ciphertext and a decapsulation +// key. If the ciphertext is not valid, Decapsulate returns an error. +// +// The shared key must be kept secret. +func (dk *DecapsulationKey1024) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) { + return dk.key.Decapsulate(ciphertext) +} + +// EncapsulationKey returns the public encapsulation key necessary to produce +// ciphertexts. +func (dk *DecapsulationKey1024) EncapsulationKey() *EncapsulationKey1024 { + return &EncapsulationKey1024{dk.key.EncapsulationKey()} +} + +// An EncapsulationKey1024 is the public key used to produce ciphertexts to be +// decapsulated by the corresponding DecapsulationKey1024. +type EncapsulationKey1024 struct { + key *mlkem.EncapsulationKey1024 +} + +// NewEncapsulationKey1024 parses an encapsulation key from its encoded form. If +// the encapsulation key is not valid, NewEncapsulationKey1024 returns an error. +func NewEncapsulationKey1024(encapsulationKey []byte) (*EncapsulationKey1024, error) { + key, err := mlkem.NewEncapsulationKey1024(encapsulationKey) + if err != nil { + return nil, err + } + + return &EncapsulationKey1024{key}, nil +} + +// Bytes returns the encapsulation key as a byte slice. +func (ek *EncapsulationKey1024) Bytes() []byte { + return ek.key.Bytes() +} + +// Encapsulate generates a shared key and an associated ciphertext from an +// encapsulation key, drawing random bytes from the default crypto/rand source. +// +// The shared key must be kept secret. +func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { + return ek.key.Encapsulate() +} diff --git a/crypto/mlkem/mlkem_test.go b/crypto/mlkem/mlkem_test.go new file mode 100644 index 00000000000..dad8e5b8b5f --- /dev/null +++ b/crypto/mlkem/mlkem_test.go @@ -0,0 +1,335 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mlkem + +import ( + "bytes" + "encoding/hex" + "flag" + "testing" + + "crypto/rand" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" +) + +type encapsulationKey interface { + Bytes() []byte + Encapsulate() ([]byte, []byte) +} + +type decapsulationKey[E encapsulationKey] interface { + Bytes() []byte + Decapsulate([]byte) ([]byte, error) + EncapsulationKey() E +} + +func TestRoundTrip(t *testing.T) { + t.Run("768", func(t *testing.T) { + testRoundTrip(t, GenerateKey768, NewEncapsulationKey768, NewDecapsulationKey768) + }) + t.Run("1024", func(t *testing.T) { + testRoundTrip(t, GenerateKey1024, NewEncapsulationKey1024, NewDecapsulationKey1024) + }) +} + +func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( + t *testing.T, generateKey func() (D, error), + newEncapsulationKey func([]byte) (E, error), + newDecapsulationKey func([]byte) (D, error)) { + dk, err := generateKey() + if err != nil { + t.Fatal(err) + } + ek := dk.EncapsulationKey() + Ke, c := ek.Encapsulate() + Kd, err := dk.Decapsulate(c) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(Ke, Kd) { + t.Fail() + } + + ek1, err := newEncapsulationKey(ek.Bytes()) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(ek.Bytes(), ek1.Bytes()) { + t.Fail() + } + dk1, err := newDecapsulationKey(dk.Bytes()) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(dk.Bytes(), dk1.Bytes()) { + t.Fail() + } + Ke1, c1 := ek1.Encapsulate() + Kd1, err := dk1.Decapsulate(c1) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(Ke1, Kd1) { + t.Fail() + } + + dk2, err := generateKey() + if err != nil { + t.Fatal(err) + } + if bytes.Equal(dk.EncapsulationKey().Bytes(), dk2.EncapsulationKey().Bytes()) { + t.Fail() + } + if bytes.Equal(dk.Bytes(), dk2.Bytes()) { + t.Fail() + } + + Ke2, c2 := dk.EncapsulationKey().Encapsulate() + if bytes.Equal(c, c2) { + t.Fail() + } + if bytes.Equal(Ke, Ke2) { + t.Fail() + } +} + +func TestBadLengths(t *testing.T) { + t.Run("768", func(t *testing.T) { + testBadLengths(t, GenerateKey768, NewEncapsulationKey768, NewDecapsulationKey768) + }) + t.Run("1024", func(t *testing.T) { + testBadLengths(t, GenerateKey1024, NewEncapsulationKey1024, NewDecapsulationKey1024) + }) +} + +func testBadLengths[E encapsulationKey, D decapsulationKey[E]]( + t *testing.T, generateKey func() (D, error), + newEncapsulationKey func([]byte) (E, error), + newDecapsulationKey func([]byte) (D, error)) { + dk, err := generateKey() + dkBytes := dk.Bytes() + if err != nil { + t.Fatal(err) + } + ek := dk.EncapsulationKey() + ekBytes := dk.EncapsulationKey().Bytes() + _, c := ek.Encapsulate() + + for i := 0; i < len(dkBytes)-1; i++ { + if _, err := newDecapsulationKey(dkBytes[:i]); err == nil { + t.Errorf("expected error for dk length %d", i) + } + } + dkLong := dkBytes + for i := 0; i < 100; i++ { + dkLong = append(dkLong, 0) + if _, err := newDecapsulationKey(dkLong); err == nil { + t.Errorf("expected error for dk length %d", len(dkLong)) + } + } + + for i := 0; i < len(ekBytes)-1; i++ { + if _, err := newEncapsulationKey(ekBytes[:i]); err == nil { + t.Errorf("expected error for ek length %d", i) + } + } + ekLong := ekBytes + for i := 0; i < 100; i++ { + ekLong = append(ekLong, 0) + if _, err := newEncapsulationKey(ekLong); err == nil { + t.Errorf("expected error for ek length %d", len(ekLong)) + } + } + + for i := 0; i < len(c)-1; i++ { + if _, err := dk.Decapsulate(c[:i]); err == nil { + t.Errorf("expected error for c length %d", i) + } + } + cLong := c + for i := 0; i < 100; i++ { + cLong = append(cLong, 0) + if _, err := dk.Decapsulate(cLong); err == nil { + t.Errorf("expected error for c length %d", len(cLong)) + } + } +} + +var millionFlag = flag.Bool("million", false, "run the million vector test") + +// TestAccumulated accumulates 10k (or 100, or 1M) random vectors and checks the +// hash of the result, to avoid checking in 150MB of test vectors. +func TestAccumulated(t *testing.T) { + n := 10000 + expected := "8a518cc63da366322a8e7a818c7a0d63483cb3528d34a4cf42f35d5ad73f22fc" + if testing.Short() { + n = 100 + expected = "1114b1b6699ed191734fa339376afa7e285c9e6acf6ff0177d346696ce564415" + } + if *millionFlag { + n = 1000000 + expected = "424bf8f0e8ae99b78d788a6e2e8e9cdaf9773fc0c08a6f433507cb559edfd0f0" + } + + s := sha3.NewShake128() + o := sha3.NewShake128() + seed := make([]byte, SeedSize) + var msg [32]byte + ct1 := make([]byte, CiphertextSize768) + + for i := 0; i < n; i++ { + s.Read(seed) + dk, err := NewDecapsulationKey768(seed) + if err != nil { + t.Fatal(err) + } + ek := dk.EncapsulationKey() + o.Write(ek.Bytes()) + + s.Read(msg[:]) + k, ct := ek.key.EncapsulateInternal(&msg) + o.Write(ct) + o.Write(k) + + kk, err := dk.Decapsulate(ct) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(kk, k) { + t.Errorf("k: got %x, expected %x", kk, k) + } + + s.Read(ct1) + k1, err := dk.Decapsulate(ct1) + if err != nil { + t.Fatal(err) + } + o.Write(k1) + } + + got := hex.EncodeToString(o.Sum(nil)) + if got != expected { + t.Errorf("got %s, expected %s", got, expected) + } +} + +var sink byte + +func BenchmarkKeyGen(b *testing.B) { + var d, z [32]byte + rand.Read(d[:]) + rand.Read(z[:]) + b.ResetTimer() + for i := 0; i < b.N; i++ { + dk := mlkem.GenerateKeyInternal768(&d, &z) + sink ^= dk.EncapsulationKey().Bytes()[0] + } +} + +func BenchmarkEncaps(b *testing.B) { + seed := make([]byte, SeedSize) + rand.Read(seed) + var m [32]byte + rand.Read(m[:]) + dk, err := NewDecapsulationKey768(seed) + if err != nil { + b.Fatal(err) + } + ekBytes := dk.EncapsulationKey().Bytes() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ek, err := NewEncapsulationKey768(ekBytes) + if err != nil { + b.Fatal(err) + } + K, c := ek.key.EncapsulateInternal(&m) + sink ^= c[0] ^ K[0] + } +} + +func BenchmarkDecaps(b *testing.B) { + dk, err := GenerateKey768() + if err != nil { + b.Fatal(err) + } + ek := dk.EncapsulationKey() + _, c := ek.Encapsulate() + b.ResetTimer() + for i := 0; i < b.N; i++ { + K, _ := dk.Decapsulate(c) + sink ^= K[0] + } +} + +func BenchmarkRoundTrip(b *testing.B) { + dk, err := GenerateKey768() + if err != nil { + b.Fatal(err) + } + ek := dk.EncapsulationKey() + ekBytes := ek.Bytes() + _, c := ek.Encapsulate() + if err != nil { + b.Fatal(err) + } + b.Run("Alice", func(b *testing.B) { + for i := 0; i < b.N; i++ { + dkS, err := GenerateKey768() + if err != nil { + b.Fatal(err) + } + ekS := dkS.EncapsulationKey().Bytes() + sink ^= ekS[0] + + Ks, err := dk.Decapsulate(c) + if err != nil { + b.Fatal(err) + } + sink ^= Ks[0] + } + }) + b.Run("Bob", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ek, err := NewEncapsulationKey768(ekBytes) + if err != nil { + b.Fatal(err) + } + Ks, cS := ek.Encapsulate() + if err != nil { + b.Fatal(err) + } + sink ^= cS[0] ^ Ks[0] + } + }) +} + +// Test that the constants from the public API match the corresponding values from the internal API. +func TestConstantSizes(t *testing.T) { + if SharedKeySize != mlkem.SharedKeySize { + t.Errorf("SharedKeySize mismatch: got %d, want %d", SharedKeySize, mlkem.SharedKeySize) + } + + if SeedSize != mlkem.SeedSize { + t.Errorf("SeedSize mismatch: got %d, want %d", SeedSize, mlkem.SeedSize) + } + + if CiphertextSize768 != mlkem.CiphertextSize768 { + t.Errorf("CiphertextSize768 mismatch: got %d, want %d", CiphertextSize768, mlkem.CiphertextSize768) + } + + if EncapsulationKeySize768 != mlkem.EncapsulationKeySize768 { + t.Errorf("EncapsulationKeySize768 mismatch: got %d, want %d", EncapsulationKeySize768, mlkem.EncapsulationKeySize768) + } + + if CiphertextSize1024 != mlkem.CiphertextSize1024 { + t.Errorf("CiphertextSize1024 mismatch: got %d, want %d", CiphertextSize1024, mlkem.CiphertextSize1024) + } + + if EncapsulationKeySize1024 != mlkem.EncapsulationKeySize1024 { + t.Errorf("EncapsulationKeySize1024 mismatch: got %d, want %d", EncapsulationKeySize1024, mlkem.EncapsulationKeySize1024) + } +} diff --git a/crypto/pbkdf2/pbkdf2.go b/crypto/pbkdf2/pbkdf2.go new file mode 100644 index 00000000000..4a51f875802 --- /dev/null +++ b/crypto/pbkdf2/pbkdf2.go @@ -0,0 +1,56 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package pbkdf2 implements the key derivation function PBKDF2 as defined in +// RFC 8018 (PKCS #5 v2.1). +// +// A key derivation function is useful when encrypting data based on a password +// or any other not-fully-random data. It uses a pseudorandom function to derive +// a secure encryption key based on the password. +package pbkdf2 + +import ( + "errors" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/pbkdf2" + "github.com/runZeroInc/excrypto/crypto/internal/fips140hash" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" +) + +// Key derives a key from the password, salt and iteration count, returning a +// []byte of length keyLength that can be used as cryptographic key. The key is +// derived based on the method described as PBKDF2 with the HMAC variant using +// the supplied hash function. +// +// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you +// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by +// doing: +// +// dk := pbkdf2.Key(sha1.New, []byte("some password"), salt, 4096, 32) +// +// Remember to get a good random salt. At least 8 bytes is recommended by the +// RFC. +// +// Using a higher iteration count will increase the cost of an exhaustive +// search but will also make derivation proportionally slower. +// +// keyLength must be a positive integer between 1 and (2^32 - 1) * h.Size(). +// Setting keyLength to a value outside of this range will result in an error. +func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyLength int) ([]byte, error) { + fh := fips140hash.UnwrapNew(h) + if fips140only.Enabled { + if keyLength < 112/8 { + return nil, errors.New("crypto/pbkdf2: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode") + } + if len(salt) < 128/8 { + return nil, errors.New("crypto/pbkdf2: use of salts shorter than 128 bits is not allowed in FIPS 140-only mode") + } + if !fips140only.ApprovedHash(fh()) { + return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + } + return pbkdf2.Key(fh, password, salt, iter, keyLength) +} diff --git a/crypto/pbkdf2/pbkdf2_test.go b/crypto/pbkdf2/pbkdf2_test.go new file mode 100644 index 00000000000..ce8ebaf8642 --- /dev/null +++ b/crypto/pbkdf2/pbkdf2_test.go @@ -0,0 +1,255 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pbkdf2_test + +import ( + "bytes" + "testing" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/pbkdf2" + "github.com/runZeroInc/excrypto/crypto/sha1" + "github.com/runZeroInc/excrypto/crypto/sha256" +) + +type testVector struct { + password string + salt string + iter int + output []byte +} + +// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 +var sha1TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1, + }, + }, + // // This one takes too long + // { + // "password", + // "salt", + // 16777216, + // []byte{ + // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + // 0x26, 0x34, 0xe9, 0x84, + // }, + // }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, + }, + }, +} + +// Test vectors from +// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors +var sha256TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, + 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, + 0xa8, 0x65, 0x48, 0xc9, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, + 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, + 0x96, 0x28, 0x93, 0xa0, + }, + }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, + 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, + 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, + 0x1c, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, + 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, + }, + }, +} + +func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { + for i, v := range vectors { + o, err := pbkdf2.Key(h, v.password, []byte(v.salt), v.iter, len(v.output)) + if err != nil { + t.Error(err) + } + if !bytes.Equal(o, v.output) { + t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) + } + } +} + +func TestWithHMACSHA1(t *testing.T) { + testHash(t, sha1.New, "SHA1", sha1TestVectors) +} + +func TestWithHMACSHA256(t *testing.T) { + testHash(t, sha256.New, "SHA256", sha256TestVectors) +} + +var sink uint8 + +func benchmark(b *testing.B, h func() hash.Hash) { + var err error + password := make([]byte, h().Size()) + salt := make([]byte, 8) + for i := 0; i < b.N; i++ { + password, err = pbkdf2.Key(h, string(password), salt, 4096, len(password)) + if err != nil { + b.Error(err) + } + } + sink += password[0] +} + +func BenchmarkHMACSHA1(b *testing.B) { + benchmark(b, sha1.New) +} + +func BenchmarkHMACSHA256(b *testing.B) { + benchmark(b, sha256.New) +} + +func TestPBKDF2ServiceIndicator(t *testing.T) { + if boring.Enabled { + t.Skip("in BoringCrypto mode PBKDF2 is not from the Go FIPS module") + } + + goodSalt := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10} + + fips140.ResetServiceIndicator() + _, err := pbkdf2.Key(sha256.New, "password", goodSalt, 1, 32) + if err != nil { + t.Error(err) + } + if !fips140.ServiceIndicator() { + t.Error("FIPS service indicator should be set") + } + + // Salt too short + fips140.ResetServiceIndicator() + _, err = pbkdf2.Key(sha256.New, "password", goodSalt[:8], 1, 32) + if err != nil { + t.Error(err) + } + if fips140.ServiceIndicator() { + t.Error("FIPS service indicator should not be set") + } + + // Key length too short + fips140.ResetServiceIndicator() + _, err = pbkdf2.Key(sha256.New, "password", goodSalt, 1, 10) + if err != nil { + t.Error(err) + } + if fips140.ServiceIndicator() { + t.Error("FIPS service indicator should not be set") + } +} + +func TestMaxKeyLength(t *testing.T) { + // This error cannot be triggered on platforms where int is 31 bits (i.e. + // 32-bit platforms), since the max value for keyLength is 1<<31-1 and + // 1<<31-1 * hLen will always be less than 1<<32-1 * hLen. + keySize := int64(1<<63 - 1) + if int64(int(keySize)) != keySize { + t.Skip("cannot be replicated on platforms where int is 31 bits") + } + _, err := pbkdf2.Key(sha256.New, "password", []byte("salt"), 1, int(keySize)) + if err == nil { + t.Fatal("expected pbkdf2.Key to fail with extremely large keyLength") + } + keySize = int64(1<<32-1) * (sha256.Size + 1) + _, err = pbkdf2.Key(sha256.New, "password", []byte("salt"), 1, int(keySize)) + if err == nil { + t.Fatal("expected pbkdf2.Key to fail with extremely large keyLength") + } +} + +func TestZeroKeyLength(t *testing.T) { + _, err := pbkdf2.Key(sha256.New, "password", []byte("salt"), 1, 0) + if err == nil { + t.Fatal("expected pbkdf2.Key to fail with zero keyLength") + } + _, err = pbkdf2.Key(sha256.New, "password", []byte("salt"), 1, -1) + if err == nil { + t.Fatal("expected pbkdf2.Key to fail with negative keyLength") + } +} diff --git a/crypto/purego_test.go b/crypto/purego_test.go new file mode 100644 index 00000000000..d88211bb219 --- /dev/null +++ b/crypto/purego_test.go @@ -0,0 +1,59 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crypto_test + +/* +// TestPureGoTag checks that when built with the purego build tag, crypto +// packages don't require any assembly. This is used by alternative compilers +// such as TinyGo. See also the "crypto/...:purego" test in cmd/dist, which +// ensures the packages build correctly. +func TestPureGoTag(t *testing.T) { + cmd := exec.Command(testenv.GoToolPath(t), "list", "-e", "crypto/...", "math/big") + cmd.Env = append(cmd.Env, "GOOS=linux") + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + log.Fatalf("loading package list: %v\n%s", err, out) + } + pkgs := strings.Split(strings.TrimSpace(string(out)), "\n") + + cmd = exec.Command(testenv.GoToolPath(t), "tool", "dist", "list") + cmd.Stderr = os.Stderr + out, err = cmd.Output() + if err != nil { + log.Fatalf("loading architecture list: %v\n%s", err, out) + } + allGOARCH := make(map[string]bool) + for _, pair := range strings.Split(strings.TrimSpace(string(out)), "\n") { + GOARCH := strings.Split(pair, "/")[1] + allGOARCH[GOARCH] = true + } + + for _, pkgName := range pkgs { + if strings.Contains(pkgName, "/boring") { + continue + } + + for GOARCH := range allGOARCH { + context := build.Context{ + GOOS: "linux", // darwin has custom assembly + GOARCH: GOARCH, + GOROOT: testenv.GOROOT(t), + Compiler: build.Default.Compiler, + BuildTags: []string{"purego", "math_big_pure_go"}, + } + + pkg, err := context.Import(pkgName, "", 0) + if err != nil { + t.Fatal(err) + } + if len(pkg.SFiles) == 0 { + continue + } + t.Errorf("package %s has purego assembly files on %s: %v", pkgName, GOARCH, pkg.SFiles) + } + } +} +*/ diff --git a/crypto/rand/example_test.go b/crypto/rand/example_test.go new file mode 100644 index 00000000000..cc074cceec5 --- /dev/null +++ b/crypto/rand/example_test.go @@ -0,0 +1,41 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand_test + +import ( + "crypto/rand" + "fmt" + "math/big" +) + +// ExampleInt prints a single cryptographically secure pseudorandom number between 0 and 99 inclusive. +func ExampleInt() { + // Int cannot return an error when using rand.Reader. + a, _ := rand.Int(rand.Reader, big.NewInt(100)) + fmt.Println(a.Int64()) +} + +// ExamplePrime prints a cryptographically secure pseudorandom 64 bit prime number. +func ExamplePrime() { + // Prime cannot return an error when using rand.Reader and bits >= 2. + a, _ := rand.Prime(rand.Reader, 64) + fmt.Println(a.Int64()) +} + +// ExampleRead prints a cryptographically secure pseudorandom 32 byte key. +func ExampleRead() { + // Note that no error handling is necessary, as Read always succeeds. + key := make([]byte, 32) + rand.Read(key) + // The key can contain any byte value, print the key in hex. + fmt.Printf("% x\n", key) +} + +// ExampleText prints a random key encoded in base32. +func ExampleText() { + key := rand.Text() + // The key is base32 and safe to display. + fmt.Println(key) +} diff --git a/crypto/rand/rand.go b/crypto/rand/rand.go new file mode 100644 index 00000000000..5a405c4ac03 --- /dev/null +++ b/crypto/rand/rand.go @@ -0,0 +1,86 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rand implements a cryptographically secure +// random number generator. +package rand + +import ( + "fmt" + "io" + "os" + _ "unsafe" + + "crypto/rand" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/drbg" +) + +// Reader is a global, shared instance of a cryptographically +// secure random number generator. It is safe for concurrent use. +// +// - On Linux, FreeBSD, Dragonfly, and Solaris, Reader uses getrandom(2). +// - On legacy Linux (< 3.17), Reader opens /dev/urandom on first use. +// - On macOS, iOS, and OpenBSD Reader, uses arc4random_buf(3). +// - On NetBSD, Reader uses the kern.arandom sysctl. +// - On Windows, Reader uses the ProcessPrng API. +// - On js/wasm, Reader uses the Web Crypto API. +// - On wasip1/wasm, Reader uses random_get. +// +// In FIPS 140-3 mode, the output passes through an SP 800-90A Rev. 1 +// Deterministric Random Bit Generator (DRBG). +var Reader io.Reader + +func init() { + if boring.Enabled { + Reader = boring.RandReader + return + } + Reader = &reader{} +} + +type reader struct { + drbg.DefaultReader +} + +func (r *reader) Read(b []byte) (n int, err error) { + boring.Unreachable() + if fips140.Enabled { + drbg.Read(b) + } else { + rand.Read(b) + } + return len(b), nil +} + +func fatal(msg string) { + fmt.Fprintf(os.Stderr, "crypto/rand: %s\n", msg) +} + +// Read fills b with cryptographically secure random bytes. It never returns an +// error, and always fills b entirely. +// +// Read calls [io.ReadFull] on [Reader] and crashes the program irrecoverably if +// an error is returned. The default Reader uses operating system APIs that are +// documented to never return an error on all but legacy Linux systems. +func Read(b []byte) (n int, err error) { + // We don't want b to escape to the heap, but escape analysis can't see + // through a potentially overridden Reader, so we special-case the default + // case which we can keep non-escaping, and in the general case we read into + // a heap buffer and copy from it. + if r, ok := Reader.(*reader); ok { + _, err = r.Read(b) + } else { + bb := make([]byte, len(b)) + _, err = io.ReadFull(Reader, bb) + copy(b, bb) + } + if err != nil { + fatal("crypto/rand: failed to read random data (see https://go.dev/issue/66821): " + err.Error()) + panic("unreachable") // To be sure. + } + return len(b), nil +} diff --git a/crypto/rand/rand_test.go b/crypto/rand/rand_test.go new file mode 100644 index 00000000000..5e2dc58f27e --- /dev/null +++ b/crypto/rand/rand_test.go @@ -0,0 +1,215 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "bytes" + "compress/flate" + "io" + "sync" + "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" +) + +// These tests are mostly duplicates of the tests in crypto/internal/sysrand, +// and testing both the Reader and Read is pretty redundant when one calls the +// other, but better safe than sorry. + +func testReadAndReader(t *testing.T, f func(*testing.T, func([]byte) (int, error))) { + t.Run("Read", func(t *testing.T) { + f(t, Read) + }) + t.Run("Reader.Read", func(t *testing.T) { + f(t, Reader.Read) + }) +} + +func TestRead(t *testing.T) { + testReadAndReader(t, testRead) +} + +func testRead(t *testing.T, Read func([]byte) (int, error)) { + var n int = 4e6 + if testing.Short() { + n = 1e5 + } + b := make([]byte, n) + n, err := Read(b) + if n != len(b) || err != nil { + t.Fatalf("Read(buf) = %d, %s", n, err) + } + + var z bytes.Buffer + f, _ := flate.NewWriter(&z, 5) + f.Write(b) + f.Close() + if z.Len() < len(b)*99/100 { + t.Fatalf("Compressed %d -> %d", len(b), z.Len()) + } +} + +func TestReadByteValues(t *testing.T) { + testReadAndReader(t, testReadByteValues) +} + +func testReadByteValues(t *testing.T, Read func([]byte) (int, error)) { + b := make([]byte, 1) + v := make(map[byte]bool) + for { + n, err := Read(b) + if n != 1 || err != nil { + t.Fatalf("Read(b) = %d, %v", n, err) + } + v[b[0]] = true + if len(v) == 256 { + break + } + } +} + +func TestLargeRead(t *testing.T) { + testReadAndReader(t, testLargeRead) +} + +func testLargeRead(t *testing.T, Read func([]byte) (int, error)) { + // 40MiB, more than the documented maximum of 32Mi-1 on Linux 32-bit. + b := make([]byte, 40<<20) + if n, err := Read(b); err != nil { + t.Fatal(err) + } else if n != len(b) { + t.Fatalf("Read(b) = %d, want %d", n, len(b)) + } +} + +func TestReadEmpty(t *testing.T) { + testReadAndReader(t, testReadEmpty) +} + +func testReadEmpty(t *testing.T, Read func([]byte) (int, error)) { + n, err := Read(make([]byte, 0)) + if n != 0 || err != nil { + t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err) + } + n, err = Read(nil) + if n != 0 || err != nil { + t.Fatalf("Read(nil) = %d, %v", n, err) + } +} + +type readerFunc func([]byte) (int, error) + +func (f readerFunc) Read(b []byte) (int, error) { + return f(b) +} + +func TestReadUsesReader(t *testing.T) { + var called bool + defer func(r io.Reader) { Reader = r }(Reader) + Reader = readerFunc(func(b []byte) (int, error) { + called = true + return len(b), nil + }) + n, err := Read(make([]byte, 32)) + if n != 32 || err != nil { + t.Fatalf("Read(make([]byte, 32)) = %d, %v", n, err) + } + if !called { + t.Error("Read did not use Reader") + } +} + +func TestConcurrentRead(t *testing.T) { + testReadAndReader(t, testConcurrentRead) +} + +func testConcurrentRead(t *testing.T, Read func([]byte) (int, error)) { + if testing.Short() { + t.Skip("skipping in short mode") + } + const N = 100 + const M = 1000 + var wg sync.WaitGroup + wg.Add(N) + for i := 0; i < N; i++ { + go func() { + defer wg.Done() + for i := 0; i < M; i++ { + b := make([]byte, 32) + n, err := Read(b) + if n != 32 || err != nil { + t.Errorf("Read = %d, %v", n, err) + } + } + }() + } + wg.Wait() +} + +var sink byte + +func TestAllocations(t *testing.T) { + cryptotest.SkipTestAllocations(t) + n := int(testing.AllocsPerRun(10, func() { + buf := make([]byte, 32) + Read(buf) + sink ^= buf[0] + })) + if n > 0 { + t.Errorf("allocs = %d, want 0", n) + } +} + +/* +func TestReadError(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + // We run this test in a subprocess because it's expected to crash. + if os.Getenv("GO_TEST_READ_ERROR") == "1" { + defer func(r io.Reader) { Reader = r }(Reader) + Reader = readerFunc(func([]byte) (int, error) { + return 0, errors.New("error") + }) + Read(make([]byte, 32)) + t.Error("Read did not crash") + return + } + + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestReadError$") + cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1") + out, err := cmd.CombinedOutput() + if err == nil { + t.Error("subprocess succeeded unexpectedly") + } + exp := "fatal error: crypto/rand: failed to read random data" + if !bytes.Contains(out, []byte(exp)) { + t.Errorf("subprocess output does not contain %q: %s", exp, out) + } +} +*/ + +func BenchmarkRead(b *testing.B) { + b.Run("4", func(b *testing.B) { + benchmarkRead(b, 4) + }) + b.Run("32", func(b *testing.B) { + benchmarkRead(b, 32) + }) + b.Run("4K", func(b *testing.B) { + benchmarkRead(b, 4<<10) + }) +} + +func benchmarkRead(b *testing.B, size int) { + b.SetBytes(int64(size)) + buf := make([]byte, size) + for i := 0; i < b.N; i++ { + if _, err := Read(buf); err != nil { + b.Fatal(err) + } + } +} diff --git a/crypto/rand/text.go b/crypto/rand/text.go new file mode 100644 index 00000000000..176326dd96a --- /dev/null +++ b/crypto/rand/text.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +const base32alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" + +// Text returns a cryptographically random string using the standard RFC 4648 base32 alphabet +// for use when a secret string, token, password, or other text is needed. +// The result contains at least 128 bits of randomness, enough to prevent brute force +// guessing attacks and to make the likelihood of collisions vanishingly small. +// A future version may return longer texts as needed to maintain those properties. +func Text() string { + // ⌈log₃₂ 2¹²⁸⌉ = 26 chars + src := make([]byte, 26) + Read(src) + for i := range src { + src[i] = base32alphabet[src[i]%32] + } + return string(src) +} diff --git a/crypto/rand/text_test.go b/crypto/rand/text_test.go new file mode 100644 index 00000000000..062f6a9870c --- /dev/null +++ b/crypto/rand/text_test.go @@ -0,0 +1,71 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand_test + +import ( + "crypto/rand" + "fmt" + "testing" +) + +func TestText(t *testing.T) { + set := make(map[string]struct{}) // hold every string produced + var indexSet [26]map[rune]int // hold every char produced at every position + for i := range indexSet { + indexSet[i] = make(map[rune]int) + } + + // not getting a char in a position: (31/32)¹⁰⁰⁰ = 1.6e-14 + // test completion within 1000 rounds: (1-(31/32)¹⁰⁰⁰)²⁶ = 0.9999999999996 + // empirically, this should complete within 400 rounds = 0.999921 + rounds := 1000 + var done bool + for range rounds { + s := rand.Text() + if len(s) != 26 { + t.Errorf("len(Text()) = %d, want = 26", len(s)) + } + for i, r := range s { + if ('A' > r || r > 'Z') && ('2' > r || r > '7') { + t.Errorf("Text()[%d] = %v, outside of base32 alphabet", i, r) + } + } + if _, ok := set[s]; ok { + t.Errorf("Text() = %s, duplicate of previously produced string", s) + } + set[s] = struct{}{} + + done = true + for i, r := range s { + indexSet[i][r]++ + if len(indexSet[i]) != 32 { + done = false + } + } + if done { + break + } + } + if !done { + t.Errorf("failed to produce every char at every index after %d rounds", rounds) + indexSetTable(t, indexSet) + } +} + +func indexSetTable(t *testing.T, indexSet [26]map[rune]int) { + alphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" + line := " " + for _, r := range alphabet { + line += fmt.Sprintf(" %3s", string(r)) + } + t.Log(line) + for i, set := range indexSet { + line = fmt.Sprintf("%2d:", i) + for _, r := range alphabet { + line += fmt.Sprintf(" %3d", set[r]) + } + t.Log(line) + } +} diff --git a/crypto/rand/util.go b/crypto/rand/util.go new file mode 100644 index 00000000000..d027e4c7c60 --- /dev/null +++ b/crypto/rand/util.go @@ -0,0 +1,105 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "errors" + "io" + "math/big" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" + "github.com/runZeroInc/excrypto/crypto/internal/randutil" +) + +// Prime returns a number of the given bit length that is prime with high probability. +// Prime will return error for any error returned by rand.Read or if bits < 2. +func Prime(rand io.Reader, bits int) (*big.Int, error) { + if fips140only.Enabled { + return nil, errors.New("crypto/rand: use of Prime is not allowed in FIPS 140-only mode") + } + if bits < 2 { + return nil, errors.New("crypto/rand: prime size must be at least 2-bit") + } + + randutil.MaybeReadByte(rand) + + b := uint(bits % 8) + if b == 0 { + b = 8 + } + + bytes := make([]byte, (bits+7)/8) + p := new(big.Int) + + for { + if _, err := io.ReadFull(rand, bytes); err != nil { + return nil, err + } + + // Clear bits in the first byte to make sure the candidate has a size <= bits. + bytes[0] &= uint8(int(1<= 2 { + bytes[0] |= 3 << (b - 2) + } else { + // Here b==1, because b cannot be zero. + bytes[0] |= 1 + if len(bytes) > 1 { + bytes[1] |= 0x80 + } + } + // Make the value odd since an even number this large certainly isn't prime. + bytes[len(bytes)-1] |= 1 + + p.SetBytes(bytes) + if p.ProbablyPrime(20) { + return p, nil + } + } +} + +// Int returns a uniform random value in [0, max). It panics if max <= 0, and +// returns an error if rand.Read returns one. +func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) { + if max.Sign() <= 0 { + panic("crypto/rand: argument to Int is <= 0") + } + n = new(big.Int) + n.Sub(max, n.SetUint64(1)) + // bitLen is the maximum bit length needed to encode a value < max. + bitLen := n.BitLen() + if bitLen == 0 { + // the only valid result is 0 + return + } + // k is the maximum byte length needed to encode a value < max. + k := (bitLen + 7) / 8 + // b is the number of bits in the most significant byte of max-1. + b := uint(bitLen % 8) + if b == 0 { + b = 8 + } + + bytes := make([]byte, k) + + for { + _, err = io.ReadFull(rand, bytes) + if err != nil { + return nil, err + } + + // Clear bits in the first byte to increase the probability + // that the candidate is < max. + bytes[0] &= uint8(int(1< 256 { return nil, KeySizeError(k) diff --git a/crypto/rsa/boring.go b/crypto/rsa/boring.go new file mode 100644 index 00000000000..edd44bd925d --- /dev/null +++ b/crypto/rsa/boring.go @@ -0,0 +1,110 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +package rsa + +import ( + "math/big" + + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/boring/bbig" +) + +// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. +// +// The first operation on a PublicKey or PrivateKey makes a parallel +// BoringCrypto key and saves it in pubCache or privCache. +// +// We could just assume that once used in a sign/verify/encrypt/decrypt operation, +// a particular key is never again modified, but that has not been a +// stated assumption before. Just in case there is any existing code that +// does modify the key between operations, we save the original values +// alongside the cached BoringCrypto key and check that the real key +// still matches before using the cached key. The theory is that the real +// operations are significantly more expensive than the comparison. + +type boringPub struct { + key *boring.PublicKeyRSA + orig PublicKey +} + +func boringPublicKey(pub *PublicKey) (*boring.PublicKeyRSA, error) { + b = new(boringPub) + b.orig = copyPublicKey(pub) + key, err := boring.NewPublicKeyRSA(bbig.Enc(b.orig.N), bbig.Enc(big.NewInt(int64(b.orig.E)))) + if err != nil { + return nil, err + } + b.key = key + return key, nil +} + +type boringPriv struct { + key *boring.PrivateKeyRSA + orig PrivateKey +} + +func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) { + b = new(boringPriv) + b.orig = copyPrivateKey(priv) + + var N, E, D, P, Q, Dp, Dq, Qinv *big.Int + N = b.orig.N + E = big.NewInt(int64(b.orig.E)) + D = b.orig.D + if len(b.orig.Primes) == 2 { + P = b.orig.Primes[0] + Q = b.orig.Primes[1] + Dp = b.orig.Precomputed.Dp + Dq = b.orig.Precomputed.Dq + Qinv = b.orig.Precomputed.Qinv + } + key, err := boring.NewPrivateKeyRSA(bbig.Enc(N), bbig.Enc(E), bbig.Enc(D), bbig.Enc(P), bbig.Enc(Q), bbig.Enc(Dp), bbig.Enc(Dq), bbig.Enc(Qinv)) + if err != nil { + return nil, err + } + b.key = key + return key, nil +} + +func publicKeyEqual(k1, k2 *PublicKey) bool { + return k1.N != nil && + k1.N.Cmp(k2.N) == 0 && + k1.E == k2.E +} + +func copyPublicKey(k *PublicKey) PublicKey { + return PublicKey{ + N: new(big.Int).Set(k.N), + E: k.E, + } +} + +func privateKeyEqual(k1, k2 *PrivateKey) bool { + return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && + k1.D.Cmp(k2.D) == 0 +} + +func copyPrivateKey(k *PrivateKey) PrivateKey { + dst := PrivateKey{ + PublicKey: copyPublicKey(&k.PublicKey), + D: new(big.Int).Set(k.D), + } + dst.Primes = make([]*big.Int, len(k.Primes)) + for i, p := range k.Primes { + dst.Primes[i] = new(big.Int).Set(p) + } + if x := k.Precomputed.Dp; x != nil { + dst.Precomputed.Dp = new(big.Int).Set(x) + } + if x := k.Precomputed.Dq; x != nil { + dst.Precomputed.Dq = new(big.Int).Set(x) + } + if x := k.Precomputed.Qinv; x != nil { + dst.Precomputed.Qinv = new(big.Int).Set(x) + } + return dst +} diff --git a/crypto/rsa/boring_test.go b/crypto/rsa/boring_test.go new file mode 100644 index 00000000000..9bba08b5227 --- /dev/null +++ b/crypto/rsa/boring_test.go @@ -0,0 +1,153 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +// Note: Can run these tests against the non-BoringCrypto +// version of the code by using "CGO_ENABLED=0 go test". + +package rsa + +import ( + "encoding/hex" + "math/big" + "runtime" + "runtime/debug" + "sync" + "testing" + + "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/encoding/asn1" + + "crypto/rand" +) + +func TestBoringASN1Marshal(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") + + k, err := GenerateKey(rand.Reader, 128) + if err != nil { + t.Fatal(err) + } + _, err = asn1.Marshal(k.PublicKey) + if err != nil { + t.Fatal(err) + } +} + +func TestBoringVerify(t *testing.T) { + // Check that signatures that lack leading zeroes don't verify. + key := &PublicKey{ + N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"), + E: 65537, + } + + hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44") + paddedHash := fromHex("3021300906052b0e03021a05000414019c5571724fb5d0e47a4260c940e9803ba05a44") + + // signature is one byte shorter than key.N. + sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56") + + err := VerifyPKCS1v15(key, 0, paddedHash, sig) + if err == nil { + t.Errorf("raw: expected verification error") + } + + err = VerifyPKCS1v15(key, crypto.SHA1, hash, sig) + if err == nil { + t.Errorf("sha1: expected verification error") + } +} + +func BenchmarkBoringVerify(b *testing.B) { + // Check that signatures that lack leading zeroes don't verify. + key := &PublicKey{ + N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"), + E: 65537, + } + + hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44") + + // signature is one byte shorter than key.N. + sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56") + + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + err := VerifyPKCS1v15(key, crypto.SHA1, hash, sig) + if err == nil { + b.Fatalf("sha1: expected verification error") + } + } +} + +func TestBoringGenerateKey(t *testing.T) { + k, err := GenerateKey(rand.Reader, 2048) // 2048 is smallest size BoringCrypto might kick in for + if err != nil { + t.Fatal(err) + } + + // Non-Boring GenerateKey always sets CRTValues to a non-nil (possibly empty) slice. + if k.Precomputed.CRTValues == nil { + t.Fatalf("GenerateKey: Precomputed.CRTValues = nil") + } +} + +func TestBoringFinalizers(t *testing.T) { + if runtime.GOOS == "nacl" || runtime.GOOS == "js" { + // Times out on nacl and js/wasm (without BoringCrypto) + // but not clear why - probably consuming rand.Reader too quickly + // and being throttled. Also doesn't really matter. + t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + k, err := GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + + // Run test with GOGC=10, to make bug more likely. + // Without the KeepAlives, the loop usually dies after + // about 30 iterations. + defer debug.SetGCPercent(debug.SetGCPercent(10)) + for n := 0; n < 200; n++ { + // Clear the underlying BoringCrypto object cache. + privCache.Clear() + + // Race to create the underlying BoringCrypto object. + // The ones that lose the race are prime candidates for + // being GC'ed too early if the finalizers are not being + // used correctly. + var wg sync.WaitGroup + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + sum := make([]byte, 32) + _, err := SignPKCS1v15(rand.Reader, k, crypto.SHA256, sum) + if err != nil { + panic(err) // usually caused by memory corruption, so hard stop + } + }() + } + wg.Wait() + } +} + +func bigFromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("bad hex: " + hex) + } + return n +} + +func fromHex(hexStr string) []byte { + s, err := hex.DecodeString(hexStr) + if err != nil { + panic(err) + } + return s +} diff --git a/crypto/rsa/equal_test.go b/crypto/rsa/equal_test.go index f4ebad79e2f..0bcac1261c1 100644 --- a/crypto/rsa/equal_test.go +++ b/crypto/rsa/equal_test.go @@ -7,15 +7,15 @@ package rsa_test import ( "testing" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/x509" ) func TestEqual(t *testing.T) { - private, _ := rsa.GenerateKey(rand.Reader, 512) + t.Setenv("GODEBUG", "rsa1024min=0") + + private := test512Key public := &private.PublicKey if !public.Equal(public) { @@ -43,7 +43,7 @@ func TestEqual(t *testing.T) { t.Errorf("private key is not equal to itself after decoding: %v", private) } - other, _ := rsa.GenerateKey(rand.Reader, 512) + other := test512KeyTwo if public.Equal(other.Public()) { t.Errorf("different public keys are Equal") } diff --git a/crypto/rsa/example_test.go b/crypto/rsa/example_test.go index 0fdeec0c1ef..bfc86b25236 100644 --- a/crypto/rsa/example_test.go +++ b/crypto/rsa/example_test.go @@ -6,18 +6,77 @@ package rsa_test import ( "encoding/hex" + "encoding/pem" "fmt" "os" + "strings" + + "github.com/runZeroInc/excrypto/crypto" "crypto/rand" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/sha256" + "github.com/runZeroInc/excrypto/crypto/x509" ) +func ExampleGenerateKey() { + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + fmt.Fprintf(os.Stderr, "Error generating RSA key: %s", err) + return + } + + der, err := x509.MarshalPKCS8PrivateKey(privateKey) + if err != nil { + fmt.Fprintf(os.Stderr, "Error marshalling RSA private key: %s", err) + return + } + + fmt.Printf("%s", pem.EncodeToMemory(&pem.Block{ + Type: "PRIVATE KEY", + Bytes: der, + })) +} + +func ExampleGenerateKey_testKey() { + // This is an insecure, test-only key from RFC 9500, Section 2.1. + // It can be used in tests to avoid slow key generation. + block, _ := pem.Decode([]byte(strings.ReplaceAll( + `-----BEGIN RSA TESTING KEY----- +MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso +tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE +89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU +l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s +B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59 +3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+ +dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI +FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J +aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2 +BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx +IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/ +fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u +pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT +Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl +u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD +fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X +Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE +k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo +qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS +CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ +XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw +AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r +UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0 +2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5 +7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3 +-----END RSA TESTING KEY-----`, "TESTING KEY", "PRIVATE KEY"))) + testRSA2048, _ := x509.ParsePKCS1PrivateKey(block.Bytes) + + fmt.Println("Private key bit size:", testRSA2048.N.BitLen()) +} + // RSA is able to encrypt only a very limited amount of data. In order // to encrypt reasonable amounts of data a hybrid scheme is commonly // used: RSA is used to encrypt a key for a symmetric primitive like diff --git a/crypto/rsa/fips.go b/crypto/rsa/fips.go new file mode 100644 index 00000000000..650d45b2b61 --- /dev/null +++ b/crypto/rsa/fips.go @@ -0,0 +1,437 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "errors" + "io" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/rsa" + "github.com/runZeroInc/excrypto/crypto/internal/fips140hash" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" +) + +const ( + // PSSSaltLengthAuto causes the salt in a PSS signature to be as large + // as possible when signing, and to be auto-detected when verifying. + // + // When signing in FIPS 140-3 mode, the salt length is capped at the length + // of the hash function used in the signature. + PSSSaltLengthAuto = 0 + // PSSSaltLengthEqualsHash causes the salt length to equal the length + // of the hash used in the signature. + PSSSaltLengthEqualsHash = -1 +) + +// PSSOptions contains options for creating and verifying PSS signatures. +type PSSOptions struct { + // SaltLength controls the length of the salt used in the PSS signature. It + // can either be a positive number of bytes, or one of the special + // PSSSaltLength constants. + SaltLength int + + // Hash is the hash function used to generate the message digest. If not + // zero, it overrides the hash function passed to SignPSS. It's required + // when using PrivateKey.Sign. + Hash crypto.Hash +} + +// HashFunc returns opts.Hash so that [PSSOptions] implements [crypto.SignerOpts]. +func (opts *PSSOptions) HashFunc() crypto.Hash { + return opts.Hash +} + +func (opts *PSSOptions) saltLength() int { + if opts == nil { + return PSSSaltLengthAuto + } + return opts.SaltLength +} + +// SignPSS calculates the signature of digest using PSS. +// +// digest must be the result of hashing the input message using the given hash +// function. The opts argument may be nil, in which case sensible defaults are +// used. If opts.Hash is set, it overrides hash. +// +// The signature is randomized depending on the message, key, and salt size, +// using bytes from rand. Most applications should use [crypto/rand.Reader] as +// rand. +func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { + if err := checkPublicKeySize(&priv.PublicKey); err != nil { + return nil, err + } + + if opts != nil && opts.Hash != 0 { + hash = opts.Hash + } + + if boring.Enabled && rand == boring.RandReader { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err + } + return boring.SignRSAPSS(bkey, hash, digest, opts.saltLength()) + } + boring.UnreachableExceptTests() + + h := fips140hash.Unwrap(hash.New()) + + if err := checkFIPS140OnlyPrivateKey(priv); err != nil { + return nil, err + } + if fips140only.Enabled && !fips140only.ApprovedHash(h) { + return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { + return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") + } + + k, err := fipsPrivateKey(priv) + if err != nil { + return nil, err + } + + saltLength := opts.saltLength() + if fips140only.Enabled && saltLength > h.Size() { + return nil, errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode") + } + switch saltLength { + case PSSSaltLengthAuto: + saltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h) + if err != nil { + return nil, fipsError(err) + } + case PSSSaltLengthEqualsHash: + saltLength = h.Size() + default: + // If we get here saltLength is either > 0 or < -1, in the + // latter case we fail out. + if saltLength <= 0 { + return nil, errors.New("crypto/rsa: invalid PSS salt length") + } + } + + return fipsError2(rsa.SignPSS(rand, k, h, digest, saltLength)) +} + +// VerifyPSS verifies a PSS signature. +// +// A valid signature is indicated by returning a nil error. digest must be the +// result of hashing the input message using the given hash function. The opts +// argument may be nil, in which case sensible defaults are used. opts.Hash is +// ignored. +// +// The inputs are not considered confidential, and may leak through timing side +// channels, or if an attacker has control of part of the inputs. +func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { + if err := checkPublicKeySize(pub); err != nil { + return err + } + + if boring.Enabled { + bkey, err := boringPublicKey(pub) + if err != nil { + return err + } + if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil { + return ErrVerification + } + return nil + } + + h := fips140hash.Unwrap(hash.New()) + + if err := checkFIPS140OnlyPublicKey(pub); err != nil { + return err + } + if fips140only.Enabled && !fips140only.ApprovedHash(h) { + return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + + k, err := fipsPublicKey(pub) + if err != nil { + return err + } + + saltLength := opts.saltLength() + if fips140only.Enabled && saltLength > h.Size() { + return errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode") + } + switch saltLength { + case PSSSaltLengthAuto: + return fipsError(rsa.VerifyPSS(k, h, digest, sig)) + case PSSSaltLengthEqualsHash: + return fipsError(rsa.VerifyPSSWithSaltLength(k, h, digest, sig, h.Size())) + default: + return fipsError(rsa.VerifyPSSWithSaltLength(k, h, digest, sig, saltLength)) + } +} + +// EncryptOAEP encrypts the given message with RSA-OAEP. +// +// OAEP is parameterised by a hash function that is used as a random oracle. +// Encryption and decryption of a given message must use the same hash function +// and sha256.New() is a reasonable choice. +// +// The random parameter is used as a source of entropy to ensure that +// encrypting the same message twice doesn't result in the same ciphertext. +// Most applications should use [crypto/rand.Reader] as random. +// +// The label parameter may contain arbitrary data that will not be encrypted, +// but which gives important context to the message. For example, if a given +// public key is used to encrypt two types of messages then distinct label +// values could be used to ensure that a ciphertext for one purpose cannot be +// used for another by an attacker. If not required it can be empty. +// +// The message must be no longer than the length of the public modulus minus +// twice the hash length, minus a further 2. +func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) { + if err := checkPublicKeySize(pub); err != nil { + return nil, err + } + + defer hash.Reset() + + if boring.Enabled && random == boring.RandReader { + hash.Reset() + k := pub.Size() + if len(msg) > k-2*hash.Size()-2 { + return nil, ErrMessageTooLong + } + bkey, err := boringPublicKey(pub) + if err != nil { + return nil, err + } + return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label) + } + boring.UnreachableExceptTests() + + hash = fips140hash.Unwrap(hash) + + if err := checkFIPS140OnlyPublicKey(pub); err != nil { + return nil, err + } + if fips140only.Enabled && !fips140only.ApprovedHash(hash) { + return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + if fips140only.Enabled && !fips140only.ApprovedRandomReader(random) { + return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") + } + + k, err := fipsPublicKey(pub) + if err != nil { + return nil, err + } + return fipsError2(rsa.EncryptOAEP(hash, hash, random, k, msg, label)) +} + +// DecryptOAEP decrypts ciphertext using RSA-OAEP. +// +// OAEP is parameterised by a hash function that is used as a random oracle. +// Encryption and decryption of a given message must use the same hash function +// and sha256.New() is a reasonable choice. +// +// The random parameter is legacy and ignored, and it can be nil. +// +// The label parameter must match the value given when encrypting. See +// [EncryptOAEP] for details. +func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { + defer hash.Reset() + return decryptOAEP(hash, hash, priv, ciphertext, label) +} + +func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { + if err := checkPublicKeySize(&priv.PublicKey); err != nil { + return nil, err + } + + if boring.Enabled { + k := priv.Size() + if len(ciphertext) > k || + k < hash.Size()*2+2 { + return nil, ErrDecryption + } + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err + } + out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label) + if err != nil { + return nil, ErrDecryption + } + return out, nil + } + + hash = fips140hash.Unwrap(hash) + mgfHash = fips140hash.Unwrap(mgfHash) + + if err := checkFIPS140OnlyPrivateKey(priv); err != nil { + return nil, err + } + if fips140only.Enabled { + if !fips140only.ApprovedHash(hash) || !fips140only.ApprovedHash(mgfHash) { + return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + } + + k, err := fipsPrivateKey(priv) + if err != nil { + return nil, err + } + + return fipsError2(rsa.DecryptOAEP(hash, mgfHash, k, ciphertext, label)) +} + +// SignPKCS1v15 calculates the signature of hashed using +// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must +// be the result of hashing the input message using the given hash +// function. If hash is zero, hashed is signed directly. This isn't +// advisable except for interoperability. +// +// The random parameter is legacy and ignored, and it can be nil. +// +// This function is deterministic. Thus, if the set of possible +// messages is small, an attacker may be able to build a map from +// messages to signatures and identify the signed messages. As ever, +// signatures provide authenticity, not confidentiality. +func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { + var hashName string + if hash != crypto.Hash(0) { + if len(hashed) != hash.Size() { + return nil, errors.New("crypto/rsa: input must be hashed message") + } + hashName = hash.String() + } + + if err := checkPublicKeySize(&priv.PublicKey); err != nil { + return nil, err + } + + if boring.Enabled { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err + } + return boring.SignRSAPKCS1v15(bkey, hash, hashed) + } + + if err := checkFIPS140OnlyPrivateKey(priv); err != nil { + return nil, err + } + if fips140only.Enabled && !fips140only.ApprovedHash(fips140hash.Unwrap(hash.New())) { + return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + + k, err := fipsPrivateKey(priv) + if err != nil { + return nil, err + } + return fipsError2(rsa.SignPKCS1v15(k, hashName, hashed)) +} + +// VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature. +// hashed is the result of hashing the input message using the given hash +// function and sig is the signature. A valid signature is indicated by +// returning a nil error. If hash is zero then hashed is used directly. This +// isn't advisable except for interoperability. +// +// The inputs are not considered confidential, and may leak through timing side +// channels, or if an attacker has control of part of the inputs. +func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { + var hashName string + if hash != crypto.Hash(0) { + if len(hashed) != hash.Size() { + return errors.New("crypto/rsa: input must be hashed message") + } + hashName = hash.String() + } + + if err := checkPublicKeySize(pub); err != nil { + return err + } + + if boring.Enabled { + bkey, err := boringPublicKey(pub) + if err != nil { + return err + } + if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil { + return ErrVerification + } + return nil + } + + if err := checkFIPS140OnlyPublicKey(pub); err != nil { + return err + } + if fips140only.Enabled && !fips140only.ApprovedHash(fips140hash.Unwrap(hash.New())) { + return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + + k, err := fipsPublicKey(pub) + if err != nil { + return err + } + return fipsError(rsa.VerifyPKCS1v15(k, hashName, hashed, sig)) +} + +func fipsError(err error) error { + switch err { + case rsa.ErrDecryption: + return ErrDecryption + case rsa.ErrVerification: + return ErrVerification + case rsa.ErrMessageTooLong: + return ErrMessageTooLong + } + return err +} + +func fipsError2[T any](x T, err error) (T, error) { + return x, fipsError(err) +} + +func checkFIPS140OnlyPublicKey(pub *PublicKey) error { + if !fips140only.Enabled { + return nil + } + if pub.N == nil { + return errors.New("crypto/rsa: public key missing N") + } + if pub.N.BitLen() < 2048 { + return errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode") + } + if pub.N.BitLen()%2 == 1 { + return errors.New("crypto/rsa: use of keys with odd size is not allowed in FIPS 140-only mode") + } + if pub.E <= 1<<16 { + return errors.New("crypto/rsa: use of public exponent <= 2¹⁶ is not allowed in FIPS 140-only mode") + } + if pub.E&1 == 0 { + return errors.New("crypto/rsa: use of even public exponent is not allowed in FIPS 140-only mode") + } + return nil +} + +func checkFIPS140OnlyPrivateKey(priv *PrivateKey) error { + if !fips140only.Enabled { + return nil + } + if err := checkFIPS140OnlyPublicKey(&priv.PublicKey); err != nil { + return err + } + if len(priv.Primes) != 2 { + return errors.New("crypto/rsa: use of multi-prime keys is not allowed in FIPS 140-only mode") + } + if priv.Primes[0] == nil || priv.Primes[1] == nil || priv.Primes[0].BitLen() != priv.Primes[1].BitLen() { + return errors.New("crypto/rsa: use of primes of different sizes is not allowed in FIPS 140-only mode") + } + return nil +} diff --git a/crypto/rsa/pkcs1v15.go b/crypto/rsa/pkcs1v15.go index 7dbff21002e..3c220c8f5f6 100644 --- a/crypto/rsa/pkcs1v15.go +++ b/crypto/rsa/pkcs1v15.go @@ -5,12 +5,12 @@ package rsa import ( - "bytes" "errors" "io" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/rsa" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/internal/randutil" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -41,11 +41,16 @@ type PKCS1v15DecryptOptions struct { // WARNING: use of this function to encrypt plaintexts other than // session keys is dangerous. Use RSA OAEP in new protocols. func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) { - randutil.MaybeReadByte(random) + if fips140only.Enabled { + return nil, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode") + } - if err := checkPub(pub); err != nil { + if err := checkPublicKeySize(pub); err != nil { return nil, err } + + randutil.MaybeReadByte(random) + k := pub.Size() if len(msg) > k-11 { return nil, ErrMessageTooLong @@ -80,7 +85,11 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro return boring.EncryptRSANoPadding(bkey, em) } - return encrypt(pub, em) + fk, err := fipsPublicKey(pub) + if err != nil { + return nil, err + } + return rsa.Encrypt(fk, em) } // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5. @@ -92,7 +101,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro // forge signatures as if they had the private key. See // DecryptPKCS1v15SessionKey for a way of solving this problem. func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) { - if err := checkPub(&priv.PublicKey); err != nil { + if err := checkPublicKeySize(&priv.PublicKey); err != nil { return nil, err } @@ -153,9 +162,10 @@ func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]b // - [1] RFC 3218, Preventing the Million Message Attack on CMS, // https://www.rfc-editor.org/rfc/rfc3218.html func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error { - if err := checkPub(&priv.PublicKey); err != nil { + if err := checkPublicKeySize(&priv.PublicKey); err != nil { return err } + k := priv.Size() if k-(len(key)+3+8) < 0 { return ErrDecryption @@ -184,26 +194,34 @@ func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext [] // access patterns. If the plaintext was valid then index contains the index of // the original message in em, to allow constant time padding removal. func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { + if fips140only.Enabled { + return 0, nil, 0, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode") + } + k := priv.Size() if k < 11 { err = ErrDecryption - return + return 0, nil, 0, err } if boring.Enabled { var bkey *boring.PrivateKeyRSA bkey, err = boringPrivateKey(priv) if err != nil { - return + return 0, nil, 0, err } em, err = boring.DecryptRSANoPadding(bkey, ciphertext) if err != nil { - return + return 0, nil, 0, ErrDecryption } } else { - em, err = decrypt(priv, ciphertext, noCheck) + fk, err := fipsPrivateKey(priv) + if err != nil { + return 0, nil, 0, err + } + em, err = rsa.DecryptWithoutCheck(fk, ciphertext) if err != nil { - return + return 0, nil, 0, ErrDecryption } } @@ -252,128 +270,3 @@ func nonZeroRandomBytes(s []byte, random io.Reader) (err error) { return } - -// These are ASN1 DER structures: -// -// DigestInfo ::= SEQUENCE { -// digestAlgorithm AlgorithmIdentifier, -// digest OCTET STRING -// } -// -// For performance, we don't use the generic ASN1 encoder. Rather, we -// precompute a prefix of the digest value that makes a valid ASN1 DER string -// with the correct contents. -var hashPrefixes = map[crypto.Hash][]byte{ - crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, - crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, - crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, - crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, - crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, - crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, - crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix. - crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, -} - -// SignPKCS1v15 calculates the signature of hashed using -// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must -// be the result of hashing the input message using the given hash -// function. If hash is zero, hashed is signed directly. This isn't -// advisable except for interoperability. -// -// The random parameter is legacy and ignored, and it can be nil. -// -// This function is deterministic. Thus, if the set of possible -// messages is small, an attacker may be able to build a map from -// messages to signatures and identify the signed messages. As ever, -// signatures provide authenticity, not confidentiality. -func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { - // pkcs1v15ConstructEM is called before boring.SignRSAPKCS1v15 to return - // consistent errors, including ErrMessageTooLong. - em, err := pkcs1v15ConstructEM(&priv.PublicKey, hash, hashed) - if err != nil { - return nil, err - } - - if boring.Enabled { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err - } - return boring.SignRSAPKCS1v15(bkey, hash, hashed) - } - - return decrypt(priv, em, withCheck) -} - -func pkcs1v15ConstructEM(pub *PublicKey, hash crypto.Hash, hashed []byte) ([]byte, error) { - // Special case: crypto.Hash(0) is used to indicate that the data is - // signed directly. - var prefix []byte - if hash != 0 { - if len(hashed) != hash.Size() { - return nil, errors.New("crypto/rsa: input must be hashed message") - } - var ok bool - prefix, ok = hashPrefixes[hash] - if !ok { - return nil, errors.New("crypto/rsa: unsupported hash function") - } - } - - // EM = 0x00 || 0x01 || PS || 0x00 || T - k := pub.Size() - if k < len(prefix)+len(hashed)+2+8+1 { - return nil, ErrMessageTooLong - } - em := make([]byte, k) - em[1] = 1 - for i := 2; i < k-len(prefix)-len(hashed)-1; i++ { - em[i] = 0xff - } - copy(em[k-len(prefix)-len(hashed):], prefix) - copy(em[k-len(hashed):], hashed) - return em, nil -} - -// VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature. -// hashed is the result of hashing the input message using the given hash -// function and sig is the signature. A valid signature is indicated by -// returning a nil error. If hash is zero then hashed is used directly. This -// isn't advisable except for interoperability. -// -// The inputs are not considered confidential, and may leak through timing side -// channels, or if an attacker has control of part of the inputs. -func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { - if boring.Enabled { - bkey, err := boringPublicKey(pub) - if err != nil { - return err - } - if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil { - return ErrVerification - } - return nil - } - - // RFC 8017 Section 8.2.2: If the length of the signature S is not k - // octets (where k is the length in octets of the RSA modulus n), output - // "invalid signature" and stop. - if pub.Size() != len(sig) { - return ErrVerification - } - - em, err := encrypt(pub, sig) - if err != nil { - return ErrVerification - } - - expected, err := pkcs1v15ConstructEM(pub, hash, hashed) - if err != nil { - return ErrVerification - } - if !bytes.Equal(em, expected) { - return ErrVerification - } - - return nil -} diff --git a/crypto/rsa/pkcs1v15_test.go b/crypto/rsa/pkcs1v15_test.go index 21ee8d85006..d886c2aea4e 100644 --- a/crypto/rsa/pkcs1v15_test.go +++ b/crypto/rsa/pkcs1v15_test.go @@ -56,12 +56,14 @@ var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{ } func TestDecryptPKCS1v15(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") + decryptionFuncs := []func([]byte) ([]byte, error){ func(ciphertext []byte) (plaintext []byte, err error) { - return DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) + return DecryptPKCS1v15(nil, test512Key, ciphertext) }, func(ciphertext []byte) (plaintext []byte, err error) { - return rsaPrivateKey.Decrypt(nil, ciphertext, nil) + return test512Key.Decrypt(nil, ciphertext, nil) }, } @@ -141,9 +143,10 @@ var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ } func TestEncryptPKCS1v15SessionKey(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") for i, test := range decryptPKCS1v15SessionKeyTests { key := []byte("FAIL") - err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key) + err := DecryptPKCS1v15SessionKey(nil, test512Key, decodeBase64(test.in), key) if err != nil { t.Errorf("#%d error decrypting", i) } @@ -155,8 +158,9 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) { } func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") for i, test := range decryptPKCS1v15SessionKeyTests { - plaintext, err := rsaPrivateKey.Decrypt(rand.Reader, decodeBase64(test.in), &PKCS1v15DecryptOptions{SessionKeyLen: 4}) + plaintext, err := test512Key.Decrypt(rand.Reader, decodeBase64(test.in), &PKCS1v15DecryptOptions{SessionKeyLen: 4}) if err != nil { t.Fatalf("#%d: error decrypting: %s", i, err) } @@ -198,12 +202,13 @@ var signPKCS1v15Tests = []signPKCS1v15Test{ } func TestSignPKCS1v15(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") for i, test := range signPKCS1v15Tests { h := sha1.New() h.Write([]byte(test.in)) digest := h.Sum(nil) - s, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA1, digest) + s, err := SignPKCS1v15(nil, test512Key, crypto.SHA1, digest) if err != nil { t.Errorf("#%d %s", i, err) } @@ -216,6 +221,7 @@ func TestSignPKCS1v15(t *testing.T) { } func TestVerifyPKCS1v15(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") for i, test := range signPKCS1v15Tests { h := sha1.New() h.Write([]byte(test.in)) @@ -223,7 +229,7 @@ func TestVerifyPKCS1v15(t *testing.T) { sig, _ := hex.DecodeString(test.out) - err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA1, digest, sig) + err := VerifyPKCS1v15(&test512Key.PublicKey, crypto.SHA1, digest, sig) if err != nil { t.Errorf("#%d %s", i, err) } @@ -231,14 +237,17 @@ func TestVerifyPKCS1v15(t *testing.T) { } func TestOverlongMessagePKCS1v15(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==") - _, err := DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) + _, err := DecryptPKCS1v15(nil, test512Key, ciphertext) if err == nil { t.Error("RSA decrypted a message that was too long.") } } func TestUnpaddedSignature(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") + msg := []byte("Thu Dec 19 18:06:16 EST 2013\n") // This base64 value was generated with: // % echo Thu Dec 19 18:06:16 EST 2013 > /tmp/msg @@ -248,14 +257,14 @@ func TestUnpaddedSignature(t *testing.T) { // file. expectedSig := decodeBase64("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==") - sig, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.Hash(0), msg) + sig, err := SignPKCS1v15(nil, test512Key, crypto.Hash(0), msg) if err != nil { t.Fatalf("SignPKCS1v15 failed: %s", err) } if !bytes.Equal(sig, expectedSig) { t.Fatalf("signature is not expected value: got %x, want %x", sig, expectedSig) } - if err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.Hash(0), msg, sig); err != nil { + if err := VerifyPKCS1v15(&test512Key.PublicKey, crypto.Hash(0), msg, sig); err != nil { t.Fatalf("signature failed to verify: %s", err) } } @@ -280,16 +289,6 @@ func TestShortSessionKey(t *testing.T) { } } -var rsaPrivateKey = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- -MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 -fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu -/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu -RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ -EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A -IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS -tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V ------END RSA TESTING KEY-----`)) - func parsePublicKey(s string) *PublicKey { p, _ := pem.Decode([]byte(s)) k, err := x509.ParsePKCS1PublicKey(p.Bytes) diff --git a/crypto/rsa/pss.go b/crypto/rsa/pss.go deleted file mode 100644 index d31c15530fb..00000000000 --- a/crypto/rsa/pss.go +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package rsa - -// This file implements the RSASSA-PSS signature scheme according to RFC 8017. - -import ( - "bytes" - "errors" - "hash" - "io" - - "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/crypto/internal/boring" -) - -// Per RFC 8017, Section 9.1 -// -// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc -// -// where -// -// DB = PS || 0x01 || salt -// -// and PS can be empty so -// -// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2 -// - -func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { - // See RFC 8017, Section 9.1.1. - - hLen := hash.Size() - sLen := len(salt) - emLen := (emBits + 7) / 8 - - // 1. If the length of M is greater than the input limitation for the - // hash function (2^61 - 1 octets for SHA-1), output "message too - // long" and stop. - // - // 2. Let mHash = Hash(M), an octet string of length hLen. - - if len(mHash) != hLen { - return nil, errors.New("crypto/rsa: input must be hashed with given hash") - } - - // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. - - if emLen < hLen+sLen+2 { - return nil, ErrMessageTooLong - } - - em := make([]byte, emLen) - psLen := emLen - sLen - hLen - 2 - db := em[:psLen+1+sLen] - h := em[psLen+1+sLen : emLen-1] - - // 4. Generate a random octet string salt of length sLen; if sLen = 0, - // then salt is the empty string. - // - // 5. Let - // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; - // - // M' is an octet string of length 8 + hLen + sLen with eight - // initial zero octets. - // - // 6. Let H = Hash(M'), an octet string of length hLen. - - var prefix [8]byte - - hash.Write(prefix[:]) - hash.Write(mHash) - hash.Write(salt) - - h = hash.Sum(h[:0]) - hash.Reset() - - // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 - // zero octets. The length of PS may be 0. - // - // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length - // emLen - hLen - 1. - - db[psLen] = 0x01 - copy(db[psLen+1:], salt) - - // 9. Let dbMask = MGF(H, emLen - hLen - 1). - // - // 10. Let maskedDB = DB \xor dbMask. - - mgf1XOR(db, hash, h) - - // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in - // maskedDB to zero. - - db[0] &= 0xff >> (8*emLen - emBits) - - // 12. Let EM = maskedDB || H || 0xbc. - em[emLen-1] = 0xbc - - // 13. Output EM. - return em, nil -} - -func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { - // See RFC 8017, Section 9.1.2. - - hLen := hash.Size() - if sLen == PSSSaltLengthEqualsHash { - sLen = hLen - } - emLen := (emBits + 7) / 8 - if emLen != len(em) { - return errors.New("rsa: internal error: inconsistent length") - } - - // 1. If the length of M is greater than the input limitation for the - // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" - // and stop. - // - // 2. Let mHash = Hash(M), an octet string of length hLen. - if hLen != len(mHash) { - return ErrVerification - } - - // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. - if emLen < hLen+sLen+2 { - return ErrVerification - } - - // 4. If the rightmost octet of EM does not have hexadecimal value - // 0xbc, output "inconsistent" and stop. - if em[emLen-1] != 0xbc { - return ErrVerification - } - - // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and - // let H be the next hLen octets. - db := em[:emLen-hLen-1] - h := em[emLen-hLen-1 : emLen-1] - - // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in - // maskedDB are not all equal to zero, output "inconsistent" and - // stop. - var bitMask byte = 0xff >> (8*emLen - emBits) - if em[0] & ^bitMask != 0 { - return ErrVerification - } - - // 7. Let dbMask = MGF(H, emLen - hLen - 1). - // - // 8. Let DB = maskedDB \xor dbMask. - mgf1XOR(db, hash, h) - - // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB - // to zero. - db[0] &= bitMask - - // If we don't know the salt length, look for the 0x01 delimiter. - if sLen == PSSSaltLengthAuto { - psLen := bytes.IndexByte(db, 0x01) - if psLen < 0 { - return ErrVerification - } - sLen = len(db) - psLen - 1 - } - - // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero - // or if the octet at position emLen - hLen - sLen - 1 (the leftmost - // position is "position 1") does not have hexadecimal value 0x01, - // output "inconsistent" and stop. - psLen := emLen - hLen - sLen - 2 - for _, e := range db[:psLen] { - if e != 0x00 { - return ErrVerification - } - } - if db[psLen] != 0x01 { - return ErrVerification - } - - // 11. Let salt be the last sLen octets of DB. - salt := db[len(db)-sLen:] - - // 12. Let - // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; - // M' is an octet string of length 8 + hLen + sLen with eight - // initial zero octets. - // - // 13. Let H' = Hash(M'), an octet string of length hLen. - var prefix [8]byte - hash.Write(prefix[:]) - hash.Write(mHash) - hash.Write(salt) - - h0 := hash.Sum(nil) - - // 14. If H = H', output "consistent." Otherwise, output "inconsistent." - if !bytes.Equal(h0, h) { // TODO: constant time? - return ErrVerification - } - return nil -} - -// signPSSWithSalt calculates the signature of hashed using PSS with specified salt. -// Note that hashed must be the result of hashing the input message using the -// given hash function. salt is a random sequence of bytes whose length will be -// later used to verify the signature. -func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) { - emBits := priv.N.BitLen() - 1 - em, err := emsaPSSEncode(hashed, emBits, salt, hash.New()) - if err != nil { - return nil, err - } - - if boring.Enabled { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err - } - // Note: BoringCrypto always does decrypt "withCheck". - // (It's not just decrypt.) - s, err := boring.DecryptRSANoPadding(bkey, em) - if err != nil { - return nil, err - } - return s, nil - } - - // RFC 8017: "Note that the octet length of EM will be one less than k if - // modBits - 1 is divisible by 8 and equal to k otherwise, where k is the - // length in octets of the RSA modulus n." 🙄 - // - // This is extremely annoying, as all other encrypt and decrypt inputs are - // always the exact same size as the modulus. Since it only happens for - // weird modulus sizes, fix it by padding inefficiently. - if emLen, k := len(em), priv.Size(); emLen < k { - emNew := make([]byte, k) - copy(emNew[k-emLen:], em) - em = emNew - } - - return decrypt(priv, em, withCheck) -} - -const ( - // PSSSaltLengthAuto causes the salt in a PSS signature to be as large - // as possible when signing, and to be auto-detected when verifying. - PSSSaltLengthAuto = 0 - // PSSSaltLengthEqualsHash causes the salt length to equal the length - // of the hash used in the signature. - PSSSaltLengthEqualsHash = -1 -) - -// PSSOptions contains options for creating and verifying PSS signatures. -type PSSOptions struct { - // SaltLength controls the length of the salt used in the PSS signature. It - // can either be a positive number of bytes, or one of the special - // PSSSaltLength constants. - SaltLength int - - // Hash is the hash function used to generate the message digest. If not - // zero, it overrides the hash function passed to SignPSS. It's required - // when using PrivateKey.Sign. - Hash crypto.Hash -} - -// HashFunc returns opts.Hash so that [PSSOptions] implements [crypto.SignerOpts]. -func (opts *PSSOptions) HashFunc() crypto.Hash { - return opts.Hash -} - -func (opts *PSSOptions) saltLength() int { - if opts == nil { - return PSSSaltLengthAuto - } - return opts.SaltLength -} - -var invalidSaltLenErr = errors.New("crypto/rsa: PSSOptions.SaltLength cannot be negative") - -// SignPSS calculates the signature of digest using PSS. -// -// digest must be the result of hashing the input message using the given hash -// function. The opts argument may be nil, in which case sensible defaults are -// used. If opts.Hash is set, it overrides hash. -// -// The signature is randomized depending on the message, key, and salt size, -// using bytes from rand. Most applications should use [crypto/rand.Reader] as -// rand. -func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { - // Note that while we don't commit to deterministic execution with respect - // to the rand stream, we also don't apply MaybeReadByte, so per Hyrum's Law - // it's probably relied upon by some. It's a tolerable promise because a - // well-specified number of random bytes is included in the signature, in a - // well-specified way. - - if opts != nil && opts.Hash != 0 { - hash = opts.Hash - } - - if boring.Enabled && rand == boring.RandReader { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err - } - return boring.SignRSAPSS(bkey, hash, digest, opts.saltLength()) - } - boring.UnreachableExceptTests() - - saltLength := opts.saltLength() - switch saltLength { - case PSSSaltLengthAuto: - saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size() - if saltLength < 0 { - return nil, ErrMessageTooLong - } - case PSSSaltLengthEqualsHash: - saltLength = hash.Size() - default: - // If we get here saltLength is either > 0 or < -1, in the - // latter case we fail out. - if saltLength <= 0 { - return nil, invalidSaltLenErr - } - } - salt := make([]byte, saltLength) - if _, err := io.ReadFull(rand, salt); err != nil { - return nil, err - } - return signPSSWithSalt(priv, hash, digest, salt) -} - -// VerifyPSS verifies a PSS signature. -// -// A valid signature is indicated by returning a nil error. digest must be the -// result of hashing the input message using the given hash function. The opts -// argument may be nil, in which case sensible defaults are used. opts.Hash is -// ignored. -// -// The inputs are not considered confidential, and may leak through timing side -// channels, or if an attacker has control of part of the inputs. -func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { - if boring.Enabled { - bkey, err := boringPublicKey(pub) - if err != nil { - return err - } - if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil { - return ErrVerification - } - return nil - } - if len(sig) != pub.Size() { - return ErrVerification - } - // Salt length must be either one of the special constants (-1 or 0) - // or otherwise positive. If it is < PSSSaltLengthEqualsHash (-1) - // we return an error. - if opts.saltLength() < PSSSaltLengthEqualsHash { - return invalidSaltLenErr - } - - emBits := pub.N.BitLen() - 1 - emLen := (emBits + 7) / 8 - em, err := encrypt(pub, sig) - if err != nil { - return ErrVerification - } - - // Like in signPSSWithSalt, deal with mismatches between emLen and the size - // of the modulus. The spec would have us wire emLen into the encoding - // function, but we'd rather always encode to the size of the modulus and - // then strip leading zeroes if necessary. This only happens for weird - // modulus sizes anyway. - for len(em) > emLen && len(em) > 0 { - if em[0] != 0 { - return ErrVerification - } - em = em[1:] - } - - return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New()) -} diff --git a/crypto/rsa/pss_test.go b/crypto/rsa/pss_test.go index e01da05ee97..0d17edacb2c 100644 --- a/crypto/rsa/pss_test.go +++ b/crypto/rsa/pss_test.go @@ -6,7 +6,6 @@ package rsa_test import ( "bufio" - "bytes" "compress/bzip2" "encoding/hex" "math/big" @@ -18,65 +17,12 @@ import ( "crypto/rand" "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/internal/fips140" . "github.com/runZeroInc/excrypto/crypto/rsa" - "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/sha512" ) -func TestEMSAPSS(t *testing.T) { - // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - msg := []byte{ - 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b, - 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb, - 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2, - 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c, - 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5, - 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02, - 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c, - 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0, - 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f, - 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c, - 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba, - 0x15, 0x98, 0x90, 0xfc, - } - salt := []byte{ - 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b, - 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61, - } - expected := []byte{ - 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24, - 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2, - 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e, - 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9, - 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f, - 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c, - 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1, - 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec, - 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3, - 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb, - 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89, - 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4, - 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc, - } - - hash := sha1.New() - hash.Write(msg) - hashed := hash.Sum(nil) - - encoded, err := EMSAPSSEncode(hashed, 1023, salt, sha1.New()) - if err != nil { - t.Errorf("Error from emsaPSSEncode: %s\n", err) - } - if !bytes.Equal(encoded, expected) { - t.Errorf("Bad encoding. got %x, want %x", encoded, expected) - } - - if err = EMSAPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { - t.Errorf("Bad verification: %s", err) - } -} - // TestPSSGolden tests all the test vectors in pss-vect.txt from // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip func TestPSSGolden(t *testing.T) { @@ -171,6 +117,8 @@ func TestPSSGolden(t *testing.T) { // TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with // the default options. OpenSSL sets the salt length to be maximal. func TestPSSOpenSSL(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") + hash := crypto.SHA256 h := hash.New() h.Write([]byte("testing")) @@ -187,7 +135,7 @@ func TestPSSOpenSSL(t *testing.T) { 0x0a, 0x37, 0x9c, 0x69, } - if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil { + if err := VerifyPSS(&test512Key.PublicKey, hash, hashed, sig, nil); err != nil { t.Error(err) } } @@ -204,17 +152,20 @@ func TestPSSNilOpts(t *testing.T) { func TestPSSSigning(t *testing.T) { var saltLengthCombinations = []struct { signSaltLength, verifySaltLength int - good bool + good, fipsGood bool }{ - {PSSSaltLengthAuto, PSSSaltLengthAuto, true}, - {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true}, - {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true}, - {PSSSaltLengthEqualsHash, 8, false}, - {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false}, - {8, 8, true}, - {PSSSaltLengthAuto, 42, true}, - {PSSSaltLengthAuto, 20, false}, - {PSSSaltLengthAuto, -2, false}, + {PSSSaltLengthAuto, PSSSaltLengthAuto, true, true}, + {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true, true}, + {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true, true}, + {PSSSaltLengthEqualsHash, 8, false, false}, + {8, 8, true, true}, + {8, PSSSaltLengthAuto, true, true}, + {42, PSSSaltLengthAuto, true, true}, + // In FIPS mode, PSSSaltLengthAuto is capped at PSSSaltLengthEqualsHash. + {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false, true}, + {PSSSaltLengthAuto, 106, true, false}, + {PSSSaltLengthAuto, 20, false, true}, + {PSSSaltLengthAuto, -2, false, false}, } hash := crypto.SHA1 @@ -233,7 +184,11 @@ func TestPSSSigning(t *testing.T) { opts.SaltLength = test.verifySaltLength err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) - if (err == nil) != test.good { + good := test.good + if fips140.Enabled { + good = test.fipsGood + } + if (err == nil) != good { t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err) } } @@ -243,6 +198,7 @@ func TestPSS513(t *testing.T) { // See Issue 42741, and separately, RFC 8017: "Note that the octet length of // EM will be one less than k if modBits - 1 is divisible by 8 and equal to // k otherwise, where k is the length in octets of the RSA modulus n." + t.Setenv("GODEBUG", "rsa1024min=0") key, err := GenerateKey(rand.Reader, 513) if err != nil { t.Fatal(err) @@ -286,19 +242,18 @@ func fromHex(hexStr string) []byte { } func TestInvalidPSSSaltLength(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") key, err := GenerateKey(rand.Reader, 245) if err != nil { t.Fatal(err) } digest := sha256.Sum256([]byte("message")) - // We don't check the exact error matches, because crypto/rsa and crypto/internal/boring - // return two different error variables, which have the same content but are not equal. if _, err := SignPSS(rand.Reader, key, crypto.SHA256, digest[:], &PSSOptions{ SaltLength: -2, Hash: crypto.SHA256, - }); err.Error() != InvalidSaltLenErr.Error() { - t.Fatalf("SignPSS unexpected error: got %v, want %v", err, InvalidSaltLenErr) + }); err.Error() != "crypto/rsa: invalid PSS salt length" { + t.Fatalf("SignPSS unexpected error: got %v, want %v", err, "crypto/rsa: invalid PSS salt length") } // We don't check the specific error here, because crypto/rsa and crypto/internal/boring @@ -311,20 +266,15 @@ func TestInvalidPSSSaltLength(t *testing.T) { } func TestHashOverride(t *testing.T) { - key, err := GenerateKey(rand.Reader, 1024) - if err != nil { - t.Fatal(err) - } - digest := sha512.Sum512([]byte("message")) // opts.Hash overrides the passed hash argument. - sig, err := SignPSS(rand.Reader, key, crypto.SHA256, digest[:], &PSSOptions{Hash: crypto.SHA512}) + sig, err := SignPSS(rand.Reader, test2048Key, crypto.SHA256, digest[:], &PSSOptions{Hash: crypto.SHA512}) if err != nil { t.Fatalf("SignPSS unexpected error: got %v, want nil", err) } // VerifyPSS has the inverse behavior, opts.Hash is always ignored, check this is true. - if err := VerifyPSS(&key.PublicKey, crypto.SHA512, digest[:], sig, &PSSOptions{Hash: crypto.SHA256}); err != nil { + if err := VerifyPSS(&test2048Key.PublicKey, crypto.SHA512, digest[:], sig, &PSSOptions{Hash: crypto.SHA256}); err != nil { t.Fatalf("VerifyPSS unexpected error: got %v, want nil", err) } } diff --git a/crypto/rsa/rsa.go b/crypto/rsa/rsa.go index 7331bb54257..4be8d3c5ff6 100644 --- a/crypto/rsa/rsa.go +++ b/crypto/rsa/rsa.go @@ -20,23 +20,43 @@ // Decrypter and Signer interfaces from the crypto package. // // Operations involving private keys are implemented using constant-time -// algorithms, except for [GenerateKey], [PrivateKey.Precompute], and -// [PrivateKey.Validate]. +// algorithms, except for [GenerateKey] and for some operations involving +// deprecated multi-prime keys. +// +// # Minimum key size +// +// [GenerateKey] returns an error if a key of less than 1024 bits is requested, +// and all Sign, Verify, Encrypt, and Decrypt methods return an error if used +// with a key smaller than 1024 bits. Such keys are insecure and should not be +// used. +// +// The rsa1024min=0 GODEBUG setting suppresses this error, but we recommend +// doing so only in tests, if necessary. Tests can set this option using +// [testing.T.Setenv] or by including "//go:debug rsa1024min=0" in a *_test.go +// source file. +// +// Alternatively, see the [GenerateKey (TestKey)] example for a pregenerated +// test-only 2048-bit key. +// +// [GenerateKey (TestKey)]: https://pkg.go.dev/crypto/rsa#example-GenerateKey-TestKey package rsa import ( "errors" - "hash" "io" "math" "math/big" + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/internal/godebug" + "crypto/rand" - "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/crypto/internal/bigmod" "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/boring/bbig" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/bigmod" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/rsa" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/crypto/internal/randutil" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -45,9 +65,8 @@ var bigOne = big.NewInt(1) // A PublicKey represents the public part of an RSA key. // -// The value of the modulus N is considered secret by this library and protected -// from leaking through timing side-channels. However, neither the value of the -// exponent E nor the precise bit size of N are similarly protected. +// The values of N and E are not considered confidential, and may leak through +// side channels, or could be mathematically derived from other public values. type PublicKey struct { N *big.Int // modulus E int // public exponent @@ -86,30 +105,6 @@ type OAEPOptions struct { Label []byte } -var ( - errPublicModulus = errors.New("crypto/rsa: missing public modulus") - errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small") - errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large") -) - -// checkPub sanity checks the public key before we use it. -// We require pub.E to fit into a 32-bit integer so that we -// do not have different behavior depending on whether -// int is 32 or 64 bits. See also -// https://www.imperialviolet.org/2012/03/16/rsae.html. -func checkPub(pub *PublicKey) error { - if pub.N == nil { - return errPublicModulus - } - if pub.E < 2 { - return errPublicExponentSmall - } - if pub.E > 1<<31-1 { - return errPublicExponentLarge - } - return nil -} - // A PrivateKey represents an RSA key type PrivateKey struct { PublicKey // public part. @@ -181,9 +176,9 @@ func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.D switch opts := opts.(type) { case *OAEPOptions: if opts.MGFHash == 0 { - return decryptOAEP(opts.Hash.New(), opts.Hash.New(), rand, priv, ciphertext, opts.Label) + return decryptOAEP(opts.Hash.New(), opts.Hash.New(), priv, ciphertext, opts.Label) } else { - return decryptOAEP(opts.Hash.New(), opts.MGFHash.New(), rand, priv, ciphertext, opts.Label) + return decryptOAEP(opts.Hash.New(), opts.MGFHash.New(), priv, ciphertext, opts.Label) } case *PKCS1v15DecryptOptions: @@ -220,7 +215,7 @@ type PrecomputedValues struct { // complexity. CRTValues []CRTValue - n, p, q *bigmod.Modulus // moduli for CRT with Montgomery precomputed constants + fips *rsa.PrivateKey } // CRTValue contains the precomputed Chinese remainder theorem values. @@ -232,74 +227,66 @@ type CRTValue struct { // Validate performs basic sanity checks on the key. // It returns nil if the key is valid, or else an error describing a problem. +// +// It runs faster on valid keys if run after [PrivateKey.Precompute]. func (priv *PrivateKey) Validate() error { - if err := checkPub(&priv.PublicKey); err != nil { - return err - } + // We can operate on keys based on d alone, but it isn't possible to encode + // with [crypto/x509.MarshalPKCS1PrivateKey], which unfortunately doesn't + // return an error. + if len(priv.Primes) < 2 { + return errors.New("crypto/rsa: missing primes") + } + // If Precomputed.fips is set, then the key has been validated by + // [rsa.NewPrivateKey] or [rsa.NewPrivateKeyWithoutCRT]. + if priv.Precomputed.fips != nil { + return nil + } + _, err := priv.precompute() + return err +} - // Check that Πprimes == n. - modulus := new(big.Int).Set(bigOne) - for _, prime := range priv.Primes { - // Any primes ≤ 1 will cause divide-by-zero panics later. - if prime.Cmp(bigOne) <= 0 { - return errors.New("crypto/rsa: invalid prime value") - } - modulus.Mul(modulus, prime) - } - if modulus.Cmp(priv.N) != 0 { - return errors.New("crypto/rsa: invalid modulus") - } +// rsa1024min is a GODEBUG that re-enables weak RSA keys if set to "0". +// See https://go.dev/issue/68762. +var rsa1024min = godebug.New("rsa1024min") - // Check that de ≡ 1 mod p-1, for each prime. - // This implies that e is coprime to each p-1 as e has a multiplicative - // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = - // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 - // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. - congruence := new(big.Int) - de := new(big.Int).SetInt64(int64(priv.E)) - de.Mul(de, priv.D) - for _, prime := range priv.Primes { - pminus1 := new(big.Int).Sub(prime, bigOne) - congruence.Mod(de, pminus1) - if congruence.Cmp(bigOne) != 0 { - return errors.New("crypto/rsa: invalid exponents") +func checkKeySize(size int) error { + // excrypto: enable all key sizes by default + return nil + /* + if size >= 1024 { + return nil + } + if rsa1024min.Value() == "0" { + rsa1024min.IncNonDefault() + return nil } + return fmt.Errorf("crypto/rsa: %d-bit keys are insecure (see https://go.dev/pkg/crypto/rsa#hdr-Minimum_key_size)", size) + */ +} + +func checkPublicKeySize(k *PublicKey) error { + if k.N == nil { + return errors.New("crypto/rsa: missing public modulus") } - return nil + return checkKeySize(k.N.BitLen()) } // GenerateKey generates a random RSA private key of the given bit size. // +// If bits is less than 1024, [GenerateKey] returns an error. See the "[Minimum +// key size]" section for further details. +// // Most applications should use [crypto/rand.Reader] as rand. Note that the // returned key does not depend deterministically on the bytes read from rand, // and may change between calls and/or between versions. -func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { - return GenerateMultiPrimeKey(random, 2, bits) -} - -// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit -// size and the given random source. // -// Table 1 in "[On the Security of Multi-prime RSA]" suggests maximum numbers of -// primes for a given bit size. -// -// Although the public keys are compatible (actually, indistinguishable) from -// the 2-prime case, the private keys are not. Thus it may not be possible to -// export multi-prime private keys in certain formats or to subsequently import -// them into other code. -// -// This package does not implement CRT optimizations for multi-prime RSA, so the -// keys with more than two primes will have worse performance. -// -// Deprecated: The use of this function with a number of primes different from -// two is not recommended for the above security, compatibility, and performance -// reasons. Use [GenerateKey] instead. -// -// [On the Security of Multi-prime RSA]: http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf -func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { - randutil.MaybeReadByte(random) +// [Minimum key size]: https://pkg.go.dev/crypto/rsa#hdr-Minimum_key_size +func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { + if err := checkKeySize(bits); err != nil { + return nil, err + } - if boring.Enabled && random == boring.RandReader && nprimes == 2 && + if boring.Enabled && random == boring.RandReader && (bits == 2048 || bits == 3072 || bits == 4096) { bN, bE, bD, bP, bQ, bDp, bDq, bQinv, err := boring.GenerateKeyRSA(bits) if err != nil { @@ -318,19 +305,6 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey return nil, errors.New("crypto/rsa: generated key exponent too large") } - mn, err := bigmod.NewModulusFromBig(N) - if err != nil { - return nil, err - } - mp, err := bigmod.NewModulusFromBig(P) - if err != nil { - return nil, err - } - mq, err := bigmod.NewModulusFromBig(Q) - if err != nil { - return nil, err - } - key := &PrivateKey{ PublicKey: PublicKey{ N: N, @@ -343,14 +317,91 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey Dq: Dq, Qinv: Qinv, CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute - n: mn, - p: mp, - q: mq, }, } return key, nil } + if fips140only.Enabled && bits < 2048 { + return nil, errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode") + } + if fips140only.Enabled && bits%2 == 1 { + return nil, errors.New("crypto/rsa: use of keys with odd size is not allowed in FIPS 140-only mode") + } + if fips140only.Enabled && !fips140only.ApprovedRandomReader(random) { + return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") + } + + k, err := rsa.GenerateKey(random, bits) + if bits < 256 && err != nil { + // Toy-sized keys have a non-negligible chance of hitting two hard + // failure cases: p == q and d <= 2^(nlen / 2). + // + // Since these are impossible to hit for real keys, we don't want to + // make the production code path more complex and harder to think about + // to handle them. + // + // Instead, just rerun the whole process a total of 8 times, which + // brings the chance of failure for 32-bit keys down to the same as for + // 256-bit keys. + for i := 1; i < 8 && err != nil; i++ { + k, err = rsa.GenerateKey(random, bits) + } + } + if err != nil { + return nil, err + } + N, e, d, p, q, dP, dQ, qInv := k.Export() + key := &PrivateKey{ + PublicKey: PublicKey{ + N: new(big.Int).SetBytes(N), + E: e, + }, + D: new(big.Int).SetBytes(d), + Primes: []*big.Int{ + new(big.Int).SetBytes(p), + new(big.Int).SetBytes(q), + }, + Precomputed: PrecomputedValues{ + fips: k, + Dp: new(big.Int).SetBytes(dP), + Dq: new(big.Int).SetBytes(dQ), + Qinv: new(big.Int).SetBytes(qInv), + CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute + }, + } + return key, nil +} + +// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit +// size and the given random source. +// +// Table 1 in "[On the Security of Multi-prime RSA]" suggests maximum numbers of +// primes for a given bit size. +// +// Although the public keys are compatible (actually, indistinguishable) from +// the 2-prime case, the private keys are not. Thus it may not be possible to +// export multi-prime private keys in certain formats or to subsequently import +// them into other code. +// +// This package does not implement CRT optimizations for multi-prime RSA, so the +// keys with more than two primes will have worse performance. +// +// Deprecated: The use of this function with a number of primes different from +// two is not recommended for the above security, compatibility, and performance +// reasons. Use [GenerateKey] instead. +// +// [On the Security of Multi-prime RSA]: http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf +func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { + if nprimes == 2 { + return GenerateKey(random, bits) + } + if fips140only.Enabled { + return nil, errors.New("crypto/rsa: multi-prime RSA is not allowed in FIPS 140-only mode") + } + + randutil.MaybeReadByte(random) + priv := new(PrivateKey) priv.E = 65537 @@ -437,42 +488,11 @@ NextSetOfPrimes: } priv.Precompute() - return priv, nil -} - -// incCounter increments a four byte, big-endian counter. -func incCounter(c *[4]byte) { - if c[3]++; c[3] != 0 { - return - } - if c[2]++; c[2] != 0 { - return - } - if c[1]++; c[1] != 0 { - return + if err := priv.Validate(); err != nil { + return nil, err } - c[0]++ -} -// mgf1XOR XORs the bytes in out with a mask generated using the MGF1 function -// specified in PKCS #1 v2.1. -func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { - var counter [4]byte - var digest []byte - - done := 0 - for done < len(out) { - hash.Write(seed) - hash.Write(counter[0:4]) - digest = hash.Sum(digest[:0]) - hash.Reset() - - for i := 0; i < len(digest) && done < len(out); i++ { - out[done] ^= digest[i] - done++ - } - incCounter(&counter) - } + return priv, nil } // ErrMessageTooLong is returned when attempting to encrypt or sign a message @@ -480,303 +500,148 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { // be returned if the size of the salt is too large. var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size") -func encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) { - boring.Unreachable() +// ErrDecryption represents a failure to decrypt a message. +// It is deliberately vague to avoid adaptive attacks. +var ErrDecryption = errors.New("crypto/rsa: decryption error") - N, err := bigmod.NewModulusFromBig(pub.N) - if err != nil { - return nil, err +// ErrVerification represents a failure to verify a signature. +// It is deliberately vague to avoid adaptive attacks. +var ErrVerification = errors.New("crypto/rsa: verification error") + +// Precompute performs some calculations that speed up private key operations +// in the future. It is safe to run on non-validated private keys. +func (priv *PrivateKey) Precompute() { + if priv.Precomputed.fips != nil { + return } - m, err := bigmod.NewNat().SetBytes(plaintext, N) + + precomputed, err := priv.precompute() if err != nil { - return nil, err + // We don't have a way to report errors, so just leave the key + // unmodified. Validate will re-run precompute. + return } - e := uint(pub.E) - - return bigmod.NewNat().ExpShortVarTime(m, e, N).Bytes(N), nil + priv.Precomputed = precomputed } -// EncryptOAEP encrypts the given message with RSA-OAEP. -// -// OAEP is parameterised by a hash function that is used as a random oracle. -// Encryption and decryption of a given message must use the same hash function -// and sha256.New() is a reasonable choice. -// -// The random parameter is used as a source of entropy to ensure that -// encrypting the same message twice doesn't result in the same ciphertext. -// Most applications should use [crypto/rand.Reader] as random. -// -// The label parameter may contain arbitrary data that will not be encrypted, -// but which gives important context to the message. For example, if a given -// public key is used to encrypt two types of messages then distinct label -// values could be used to ensure that a ciphertext for one purpose cannot be -// used for another by an attacker. If not required it can be empty. -// -// The message must be no longer than the length of the public modulus minus -// twice the hash length, minus a further 2. -func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) { - // Note that while we don't commit to deterministic execution with respect - // to the random stream, we also don't apply MaybeReadByte, so per Hyrum's - // Law it's probably relied upon by some. It's a tolerable promise because a - // well-specified number of random bytes is included in the ciphertext, in a - // well-specified way. - - if err := checkPub(pub); err != nil { - return nil, err +func (priv *PrivateKey) precompute() (PrecomputedValues, error) { + var precomputed PrecomputedValues + + if priv.N == nil { + return precomputed, errors.New("crypto/rsa: missing public modulus") + } + if priv.D == nil { + return precomputed, errors.New("crypto/rsa: missing private exponent") } - hash.Reset() - k := pub.Size() - if len(msg) > k-2*hash.Size()-2 { - return nil, ErrMessageTooLong + if len(priv.Primes) != 2 { + return priv.precomputeLegacy() + } + if priv.Primes[0] == nil { + return precomputed, errors.New("crypto/rsa: prime P is nil") + } + if priv.Primes[1] == nil { + return precomputed, errors.New("crypto/rsa: prime Q is nil") } - if boring.Enabled && random == boring.RandReader { - bkey, err := boringPublicKey(pub) + // If the CRT values are already set, use them. + if priv.Precomputed.Dp != nil && priv.Precomputed.Dq != nil && priv.Precomputed.Qinv != nil { + k, err := rsa.NewPrivateKeyWithPrecomputation(priv.N.Bytes(), priv.E, priv.D.Bytes(), + priv.Primes[0].Bytes(), priv.Primes[1].Bytes(), + priv.Precomputed.Dp.Bytes(), priv.Precomputed.Dq.Bytes(), priv.Precomputed.Qinv.Bytes()) if err != nil { - return nil, err + return precomputed, err } - return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label) + precomputed = priv.Precomputed + precomputed.fips = k + precomputed.CRTValues = make([]CRTValue, 0) + return precomputed, nil } - boring.UnreachableExceptTests() - hash.Write(label) - lHash := hash.Sum(nil) - hash.Reset() + k, err := rsa.NewPrivateKey(priv.N.Bytes(), priv.E, priv.D.Bytes(), + priv.Primes[0].Bytes(), priv.Primes[1].Bytes()) + if err != nil { + return precomputed, err + } - em := make([]byte, k) - seed := em[1 : 1+hash.Size()] - db := em[1+hash.Size():] + precomputed.fips = k + _, _, _, _, _, dP, dQ, qInv := k.Export() + precomputed.Dp = new(big.Int).SetBytes(dP) + precomputed.Dq = new(big.Int).SetBytes(dQ) + precomputed.Qinv = new(big.Int).SetBytes(qInv) + precomputed.CRTValues = make([]CRTValue, 0) + return precomputed, nil +} - copy(db[0:hash.Size()], lHash) - db[len(db)-len(msg)-1] = 1 - copy(db[len(db)-len(msg):], msg) +func (priv *PrivateKey) precomputeLegacy() (PrecomputedValues, error) { + var precomputed PrecomputedValues - _, err := io.ReadFull(random, seed) + k, err := rsa.NewPrivateKeyWithoutCRT(priv.N.Bytes(), priv.E, priv.D.Bytes()) if err != nil { - return nil, err + return precomputed, err } + precomputed.fips = k - mgf1XOR(db, hash, seed) - mgf1XOR(seed, hash, db) - - if boring.Enabled { - var bkey *boring.PublicKeyRSA - bkey, err = boringPublicKey(pub) - if err != nil { - return nil, err - } - return boring.EncryptRSANoPadding(bkey, em) + if len(priv.Primes) < 2 { + return precomputed, nil } - return encrypt(pub, em) -} - -// ErrDecryption represents a failure to decrypt a message. -// It is deliberately vague to avoid adaptive attacks. -var ErrDecryption = errors.New("crypto/rsa: decryption error") - -// ErrVerification represents a failure to verify a signature. -// It is deliberately vague to avoid adaptive attacks. -var ErrVerification = errors.New("crypto/rsa: verification error") - -// Precompute performs some calculations that speed up private key operations -// in the future. -func (priv *PrivateKey) Precompute() { - if priv.Precomputed.n == nil && len(priv.Primes) == 2 { - // Precomputed values _should_ always be valid, but if they aren't - // just return. We could also panic. - var err error - priv.Precomputed.n, err = bigmod.NewModulusFromBig(priv.N) - if err != nil { - return - } - priv.Precomputed.p, err = bigmod.NewModulusFromBig(priv.Primes[0]) - if err != nil { - // Unset previous values, so we either have everything or nothing - priv.Precomputed.n = nil - return + // Ensure the Mod and ModInverse calls below don't panic. + for _, prime := range priv.Primes { + if prime == nil { + return precomputed, errors.New("crypto/rsa: prime factor is nil") } - priv.Precomputed.q, err = bigmod.NewModulusFromBig(priv.Primes[1]) - if err != nil { - // Unset previous values, so we either have everything or nothing - priv.Precomputed.n, priv.Precomputed.p = nil, nil - return + if prime.Cmp(bigOne) <= 0 { + return precomputed, errors.New("crypto/rsa: prime factor is <= 1") } } - // Fill in the backwards-compatibility *big.Int values. - if priv.Precomputed.Dp != nil { - return - } + precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne) + precomputed.Dp.Mod(priv.D, precomputed.Dp) - priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne) - priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp) + precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne) + precomputed.Dq.Mod(priv.D, precomputed.Dq) - priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne) - priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq) - - priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0]) + precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0]) + if precomputed.Qinv == nil { + return precomputed, errors.New("crypto/rsa: prime factors are not relatively prime") + } r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1]) - priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2) + precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2) for i := 2; i < len(priv.Primes); i++ { prime := priv.Primes[i] - values := &priv.Precomputed.CRTValues[i-2] + values := &precomputed.CRTValues[i-2] values.Exp = new(big.Int).Sub(prime, bigOne) values.Exp.Mod(priv.D, values.Exp) values.R = new(big.Int).Set(r) values.Coeff = new(big.Int).ModInverse(r, prime) - - r.Mul(r, prime) - } -} - -const withCheck = true -const noCheck = false - -// decrypt performs an RSA decryption of ciphertext into out. If check is true, -// m^e is calculated and compared with ciphertext, in order to defend against -// errors in the CRT computation. -func decrypt(priv *PrivateKey, ciphertext []byte, check bool) ([]byte, error) { - if len(priv.Primes) <= 2 { - boring.Unreachable() - } - - var ( - err error - m, c *bigmod.Nat - N *bigmod.Modulus - t0 = bigmod.NewNat() - ) - if priv.Precomputed.n == nil { - N, err = bigmod.NewModulusFromBig(priv.N) - if err != nil { - return nil, ErrDecryption - } - c, err = bigmod.NewNat().SetBytes(ciphertext, N) - if err != nil { - return nil, ErrDecryption - } - m = bigmod.NewNat().Exp(c, priv.D.Bytes(), N) - } else { - N = priv.Precomputed.n - P, Q := priv.Precomputed.p, priv.Precomputed.q - Qinv, err := bigmod.NewNat().SetBytes(priv.Precomputed.Qinv.Bytes(), P) - if err != nil { - return nil, ErrDecryption - } - c, err = bigmod.NewNat().SetBytes(ciphertext, N) - if err != nil { - return nil, ErrDecryption + if values.Coeff == nil { + return precomputed, errors.New("crypto/rsa: prime factors are not relatively prime") } - // m = c ^ Dp mod p - m = bigmod.NewNat().Exp(t0.Mod(c, P), priv.Precomputed.Dp.Bytes(), P) - // m2 = c ^ Dq mod q - m2 := bigmod.NewNat().Exp(t0.Mod(c, Q), priv.Precomputed.Dq.Bytes(), Q) - // m = m - m2 mod p - m.Sub(t0.Mod(m2, P), P) - // m = m * Qinv mod p - m.Mul(Qinv, P) - // m = m * q mod N - m.ExpandFor(N).Mul(t0.Mod(Q.Nat(), N), N) - // m = m + m2 mod N - m.Add(m2.ExpandFor(N), N) - } - - if check { - c1 := bigmod.NewNat().ExpShortVarTime(m, uint(priv.E), N) - if c1.Equal(c) != 1 { - return nil, ErrDecryption - } + r.Mul(r, prime) } - return m.Bytes(N), nil + return precomputed, nil } -// DecryptOAEP decrypts ciphertext using RSA-OAEP. -// -// OAEP is parameterised by a hash function that is used as a random oracle. -// Encryption and decryption of a given message must use the same hash function -// and sha256.New() is a reasonable choice. -// -// The random parameter is legacy and ignored, and it can be nil. -// -// The label parameter must match the value given when encrypting. See -// [EncryptOAEP] for details. -func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { - return decryptOAEP(hash, hash, random, priv, ciphertext, label) -} - -func decryptOAEP(hash, mgfHash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { - if err := checkPub(&priv.PublicKey); err != nil { +func fipsPublicKey(pub *PublicKey) (*rsa.PublicKey, error) { + N, err := bigmod.NewModulus(pub.N.Bytes()) + if err != nil { return nil, err } - k := priv.Size() - if len(ciphertext) > k || - k < hash.Size()*2+2 { - return nil, ErrDecryption - } + return &rsa.PublicKey{N: N, E: pub.E}, nil +} - if boring.Enabled { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err - } - out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label) - if err != nil { - return nil, ErrDecryption - } - return out, nil +func fipsPrivateKey(priv *PrivateKey) (*rsa.PrivateKey, error) { + if priv.Precomputed.fips != nil { + return priv.Precomputed.fips, nil } - - em, err := decrypt(priv, ciphertext, noCheck) + precomputed, err := priv.precompute() if err != nil { return nil, err } - - hash.Write(label) - lHash := hash.Sum(nil) - hash.Reset() - - firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) - - seed := em[1 : hash.Size()+1] - db := em[hash.Size()+1:] - - mgf1XOR(seed, mgfHash, db) - mgf1XOR(db, mgfHash, seed) - - lHash2 := db[0:hash.Size()] - - // We have to validate the plaintext in constant time in order to avoid - // attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal - // Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1 - // v2.0. In J. Kilian, editor, Advances in Cryptology. - lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2) - - // The remainder of the plaintext must be zero or more 0x00, followed - // by 0x01, followed by the message. - // lookingForIndex: 1 iff we are still looking for the 0x01 - // index: the offset of the first 0x01 byte - // invalid: 1 iff we saw a non-zero byte before the 0x01. - var lookingForIndex, index, invalid int - lookingForIndex = 1 - rest := db[hash.Size():] - - for i := 0; i < len(rest); i++ { - equals0 := subtle.ConstantTimeByteEq(rest[i], 0) - equals1 := subtle.ConstantTimeByteEq(rest[i], 1) - index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index) - lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex) - invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid) - } - - if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 { - return nil, ErrDecryption - } - - return rest[index+1:], nil + return precomputed.fips, nil } diff --git a/crypto/rsa/rsa_export_test.go b/crypto/rsa/rsa_export_test.go index 70406decf17..6b6afa822f6 100644 --- a/crypto/rsa/rsa_export_test.go +++ b/crypto/rsa/rsa_export_test.go @@ -5,6 +5,3 @@ package rsa var NonZeroRandomBytes = nonZeroRandomBytes -var EMSAPSSEncode = emsaPSSEncode -var EMSAPSSVerify = emsaPSSVerify -var InvalidSaltLenErr = invalidSaltLenErr diff --git a/crypto/rsa/rsa_test.go b/crypto/rsa/rsa_test.go index 7f6475684f7..4a2b3ad1f9b 100644 --- a/crypto/rsa/rsa_test.go +++ b/crypto/rsa/rsa_test.go @@ -7,10 +7,13 @@ package rsa_test import ( "bufio" "bytes" + "encoding/hex" "encoding/pem" "flag" "fmt" + "io" "math/big" + "os" "strings" "testing" @@ -18,32 +21,46 @@ import ( "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" . "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/internal/testenv" ) func TestKeyGeneration(t *testing.T) { - for _, size := range []int{128, 1024, 2048, 3072} { - priv, err := GenerateKey(rand.Reader, size) - if err != nil { - t.Errorf("GenerateKey(%d): %v", size, err) - } - if bits := priv.N.BitLen(); bits != size { - t.Errorf("key too short (%d vs %d)", bits, size) - } - testKeyBasics(t, priv) - if testing.Short() { - break - } + sizes := []int{128, 512, 1024, 2048, 3072, 4096} + if testing.Short() { + sizes = sizes[:2] + } + for _, size := range sizes { + t.Run(fmt.Sprintf("%d", size), func(t *testing.T) { + // excrypto: allow small keys + /* + if size < 1024 { + _, err := GenerateKey(rand.Reader, size) + if err == nil { + t.Errorf("GenerateKey(%d) succeeded without GODEBUG", size) + } + t.Setenv("GODEBUG", "rsa1024min=0") + } + */ + priv, err := GenerateKey(rand.Reader, size) + if err != nil { + t.Errorf("GenerateKey(%d): %v", size, err) + } + if bits := priv.N.BitLen(); bits != size { + t.Errorf("key too short (%d vs %d)", bits, size) + } + testKeyBasics(t, priv) + }) } } func Test3PrimeKeyGeneration(t *testing.T) { - size := 768 + size := 1024 if testing.Short() { + t.Setenv("GODEBUG", "rsa1024min=0") size = 256 } @@ -55,8 +72,9 @@ func Test3PrimeKeyGeneration(t *testing.T) { } func Test4PrimeKeyGeneration(t *testing.T) { - size := 768 + size := 1024 if testing.Short() { + t.Setenv("GODEBUG", "rsa1024min=0") size = 256 } @@ -68,6 +86,7 @@ func Test4PrimeKeyGeneration(t *testing.T) { } func TestNPrimeKeyGeneration(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") primeSize := 64 maxN := 24 if testing.Short() { @@ -86,8 +105,9 @@ func TestNPrimeKeyGeneration(t *testing.T) { } func TestImpossibleKeyGeneration(t *testing.T) { - // This test ensures that trying to generate toy RSA keys doesn't enter - // an infinite loop. + // This test ensures that trying to generate or validate toy RSA keys + // doesn't enter an infinite loop or panic. + t.Setenv("GODEBUG", "rsa1024min=0") for i := 0; i < 32; i++ { GenerateKey(rand.Reader, i) GenerateMultiPrimeKey(rand.Reader, 3, i) @@ -96,7 +116,25 @@ func TestImpossibleKeyGeneration(t *testing.T) { } } +func TestTinyKeyGeneration(t *testing.T) { + // Toy-sized keys can randomly hit hard failures in GenerateKey. + if testing.Short() { + t.Skip("skipping in short mode") + } + t.Setenv("GODEBUG", "rsa1024min=0") + for range 10000 { + k, err := GenerateKey(rand.Reader, 32) + if err != nil { + t.Fatalf("GenerateKey(32): %v", err) + } + if err := k.Validate(); err != nil { + t.Fatalf("Validate(32): %v", err) + } + } +} + func TestGnuTLSKey(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") // This is a key generated by `certtool --generate-privkey --bits 128`. // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of // the group. @@ -134,10 +172,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { } func TestAllocations(t *testing.T) { - if boring.Enabled { - t.Skip("skipping allocations test with BoringCrypto") - } - testenv.SkipIfOptimizationOff(t) + cryptotest.SkipTestAllocations(t) m := []byte("Hello Gophers") c, err := EncryptPKCS1v15(rand.Reader, &test2048Key.PublicKey, m) @@ -161,11 +196,20 @@ func TestAllocations(t *testing.T) { var allFlag = flag.Bool("all", false, "test all key sizes up to 2048") func TestEverything(t *testing.T) { - min := 32 - max := 560 // any smaller than this and not all tests will run if testing.Short() { - min = max + // Skip key generation, but still test real sizes. + for _, key := range []*PrivateKey{test1024Key, test2048Key} { + t.Run(fmt.Sprintf("%d", key.N.BitLen()), func(t *testing.T) { + t.Parallel() + testEverything(t, key) + }) + } + return } + + t.Setenv("GODEBUG", "rsa1024min=0") + min := 32 + max := 560 // any smaller than this and not all tests will run if *allFlag { max = 2048 } @@ -175,7 +219,7 @@ func TestEverything(t *testing.T) { t.Parallel() priv, err := GenerateKey(rand.Reader, size) if err != nil { - t.Errorf("GenerateKey(%d): %v", size, err) + t.Fatalf("GenerateKey(%d): %v", size, err) } if bits := priv.N.BitLen(); bits != size { t.Errorf("key too short (%d vs %d)", bits, size) @@ -228,8 +272,14 @@ func testEverything(t *testing.T, priv *PrivateKey) { } } + const hashMsg = "crypto/rsa: input must be hashed message" + sig, err := SignPKCS1v15(nil, priv, crypto.SHA256, msg) + if err == nil || err.Error() != hashMsg { + t.Errorf("SignPKCS1v15 with bad hash: err = %q, want %q", err, hashMsg) + } + hash := sha256.Sum256(msg) - sig, err := SignPKCS1v15(nil, priv, crypto.SHA256, hash[:]) + sig, err = SignPKCS1v15(nil, priv, crypto.SHA256, hash[:]) if err == ErrMessageTooLong { t.Log("key too small for SignPKCS1v15") } else if err != nil { @@ -326,8 +376,66 @@ func testEverything(t *testing.T, priv *PrivateKey) { if err == nil { t.Errorf("DecryptPKCS1v15 accepted a long ciphertext") } + + der, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + t.Errorf("MarshalPKCS8PrivateKey: %v", err) + } + key, err := x509.ParsePKCS8PrivateKey(der) + if err != nil { + t.Errorf("ParsePKCS8PrivateKey: %v", err) + } + if !key.(*PrivateKey).Equal(priv) { + t.Errorf("private key mismatch") + } + + der, err = x509.MarshalPKIXPublicKey(&priv.PublicKey) + if err != nil { + t.Errorf("MarshalPKIXPublicKey: %v", err) + } + pub, err := x509.ParsePKIXPublicKey(der) + if err != nil { + t.Errorf("ParsePKIXPublicKey: %v", err) + } + if !pub.(*PublicKey).Equal(&priv.PublicKey) { + t.Errorf("public key mismatch") + } } +// excrypto: allow small rsa keys +/* +func TestKeyTooSmall(t *testing.T) { + checkErr := func(err error) { + t.Helper() + if err == nil { + t.Error("expected error") + } + if !strings.Contains(err.Error(), "insecure") { + t.Errorf("unexpected error: %v", err) + } + } + checkErr2 := func(_ []byte, err error) { + t.Helper() + checkErr(err) + } + + buf := make([]byte, 512/8) + checkErr2(test512Key.Sign(rand.Reader, buf, crypto.SHA512)) + checkErr2(test512Key.Sign(rand.Reader, buf, &PSSOptions{SaltLength: PSSSaltLengthEqualsHash})) + checkErr2(test512Key.Decrypt(rand.Reader, buf, &PKCS1v15DecryptOptions{})) + checkErr2(test512Key.Decrypt(rand.Reader, buf, &OAEPOptions{Hash: crypto.SHA512})) + checkErr(VerifyPKCS1v15(&test512Key.PublicKey, crypto.SHA512, buf, buf)) + checkErr(VerifyPSS(&test512Key.PublicKey, crypto.SHA512, buf, buf, &PSSOptions{SaltLength: PSSSaltLengthEqualsHash})) + checkErr2(SignPKCS1v15(rand.Reader, test512Key, crypto.SHA512, buf)) + checkErr2(SignPSS(rand.Reader, test512Key, crypto.SHA512, buf, &PSSOptions{SaltLength: PSSSaltLengthEqualsHash})) + checkErr2(EncryptPKCS1v15(rand.Reader, &test512Key.PublicKey, buf)) + checkErr2(EncryptOAEP(sha512.New(), rand.Reader, &test512Key.PublicKey, buf, nil)) + checkErr2(DecryptPKCS1v15(nil, test512Key, buf)) + checkErr2(DecryptOAEP(sha512.New(), nil, test512Key, buf, nil)) + checkErr(DecryptPKCS1v15SessionKey(nil, test512Key, buf, buf)) +} +*/ + func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } func parseKey(s string) *PrivateKey { @@ -346,7 +454,46 @@ func parseKey(s string) *PrivateKey { return k } -var test2048Key = parseKey(testingKey(`-----BEGIN TESTING KEY----- +var rsaPrivateKey = test1024Key + +var test512Key = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +-----END RSA TESTING KEY-----`)) + +var test512KeyTwo = parseKey(testingKey(`-----BEGIN TESTING KEY----- +MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEA0wLCoguSfgskR8tY +Fh2AzXQzBpSEmPucxtVe93HzPdQpxvtSTvZe5kIsdvPc7QZ0dCc/qbnUBRbuGIAl +Ir0c9QIDAQABAkAzul+AXhnhcFXKi9ziPwVOWIgRuuLupe//BluriXG53BEBSVrV +Hr7qFqwnSLSLroMzqhZwoqyRgjsLYyGEHDGBAiEA8T0sDPuht3w2Qv61IAvBwjLH +H4HXjRUEWYRn1XjHqAUCIQDf7BYlANRqFfvg1YK3VCM4YyK2mH1UivDi8wdPlJRk +MQIhAMp5i2WCNeNpD6n/WkqBU6kJMXPSaPZy82mm5feYHgt5AiEAkg/QnhB9fjma +1BzRqD4Uv0pDMXIkhooe+Rrn0OwtI3ECIQDP6nxML3JOjbAS7ydFBv176uVsMJib +r4PZozCXKuuGNg== +-----END PRIVATE KEY-----`)) + +var test1024Key = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MIICXQIBAAKBgQCw0YNSqI9T1VFvRsIOejZ9feiKz1SgGfbe9Xq5tEzt2yJCsbyg ++xtcuCswNhdqY5A1ZN7G60HbL4/Hh/TlLhFJ4zNHVylz9mDDx3yp4IIcK2lb566d +fTD0B5EQ9Iqub4twLUdLKQCBfyhmJJvsEqKxm4J4QWgI+Brh/Pm3d4piPwIDAQAB +AoGASC6fj6TkLfMNdYHLQqG9kOlPfys4fstarpZD7X+fUBJ/H/7y5DzeZLGCYAIU ++QeAHWv6TfZIQjReW7Qy00RFJdgwFlTFRCsKXhG5x+IB+jL0Grr08KbgPPDgy4Jm +xirRHZVtU8lGbkiZX+omDIU28EHLNWL6rFEcTWao/tERspECQQDp2G5Nw0qYWn7H +Wm9Up1zkUTnkUkCzhqtxHbeRvNmHGKE7ryGMJEk2RmgHVstQpsvuFY4lIUSZEjAc +DUFJERhFAkEAwZH6O1ULORp8sHKDdidyleYcZU8L7y9Y3OXJYqELfddfBgFUZeVQ +duRmJj7ryu0g0uurOTE+i8VnMg/ostxiswJBAOc64Dd8uLJWKa6uug+XPr91oi0n +OFtM+xHrNK2jc+WmcSg3UJDnAI3uqMc5B+pERLq0Dc6hStehqHjUko3RnZECQEGZ +eRYWciE+Cre5dzfZkomeXE0xBrhecV0bOq6EKWLSVE+yr6mAl05ThRK9DCfPSOpy +F6rgN3QiyCA9J/1FluUCQQC5nX+PTU1FXx+6Ri2ZCi6EjEKMHr7gHcABhMinZYOt +N59pra9UdVQw9jxCU9G7eMyb0jJkNACAuEwakX3gi27b +-----END RSA TESTING KEY-----`)) + +var test2048KeyPEM = testingKey(`-----BEGIN TESTING KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNoyFUYeDuqw+k iyv47iBy/udbWmQdpbUZ8JobHv8uQrvL7sQN6l83teHgNJsXqtiLF3MC+K+XI6Dq hxUWfQwLip8WEnv7Jx/+53S8yp/CS4Jw86Q1bQHbZjFDpcoqSuwAxlegw18HNZCY @@ -373,7 +520,9 @@ mCSL4FGK02ImUNDsd0RVVFw51DRId4rmsuJYMK9NAoGAKlYdc4784ixTD2ZICIOC ZWPxPAyQUEA7EkuUhAX1bVNG6UJTYA8kmGcUCG4jPTgWzi00IyUUr8jK7efyU/zs qiJuVs1bia+flYIQpysMl1VzZh8gW1nkB4SVPm5l2wBvVJDIr9Mc6rueC/oVNkh2 fLVGuFoTVIu2bF0cWAjNNMg= ------END TESTING KEY-----`)) +-----END TESTING KEY-----`) + +var test2048Key = parseKey(test2048KeyPEM) var test3072Key = parseKey(testingKey(`-----BEGIN TESTING KEY----- MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDJrvevql7G07LM @@ -556,19 +705,48 @@ func BenchmarkEncryptOAEP(b *testing.B) { } func BenchmarkSignPKCS1v15(b *testing.B) { - b.Run("2048", func(b *testing.B) { - hashed := sha256.Sum256([]byte("testing")) + b.Run("2048", func(b *testing.B) { benchmarkSignPKCS1v15(b, test2048Key) }) + b.Run("2048/noprecomp/OnlyD", func(b *testing.B) { + benchmarkSignPKCS1v15(b, &PrivateKey{ + PublicKey: test2048Key.PublicKey, + D: test2048Key.D, + }) + }) + b.Run("2048/noprecomp/Primes", func(b *testing.B) { + benchmarkSignPKCS1v15(b, &PrivateKey{ + PublicKey: test2048Key.PublicKey, + D: test2048Key.D, + Primes: test2048Key.Primes, + }) + }) + // This is different from "2048" because it's only the public precomputed + // values, and not the crypto/internal/fips140/rsa.PrivateKey. + b.Run("2048/noprecomp/AllValues", func(b *testing.B) { + benchmarkSignPKCS1v15(b, &PrivateKey{ + PublicKey: test2048Key.PublicKey, + D: test2048Key.D, + Primes: test2048Key.Primes, + Precomputed: PrecomputedValues{ + Dp: test2048Key.Precomputed.Dp, + Dq: test2048Key.Precomputed.Dq, + Qinv: test2048Key.Precomputed.Qinv, + }, + }) + }) +} - var sink byte - b.ResetTimer() - for i := 0; i < b.N; i++ { - s, err := SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:]) - if err != nil { - b.Fatal(err) - } - sink ^= s[0] +func benchmarkSignPKCS1v15(b *testing.B, k *PrivateKey) { + hashed := sha256.Sum256([]byte("testing")) + + var sink byte + b.ResetTimer() + for i := 0; i < b.N; i++ { + s, err := SignPKCS1v15(rand.Reader, k, crypto.SHA256, hashed[:]) + if err != nil { + b.Fatal(err) } - }) + sink ^= s[0] + } } func BenchmarkVerifyPKCS1v15(b *testing.B) { @@ -623,6 +801,70 @@ func BenchmarkVerifyPSS(b *testing.B) { }) } +func BenchmarkParsePKCS8PrivateKey(b *testing.B) { + b.Run("2048", func(b *testing.B) { + p, _ := pem.Decode([]byte(test2048KeyPEM)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := x509.ParsePKCS8PrivateKey(p.Bytes); err != nil { + b.Fatal(err) + } + } + }) +} + +func BenchmarkGenerateKey(b *testing.B) { + b.Run("2048", func(b *testing.B) { + primes, err := os.ReadFile("testdata/keygen2048.txt") + if err != nil { + b.Fatal(err) + } + for b.Loop() { + r := &testPrimeReader{primes: string(primes)} + if _, err := GenerateKey(r, 2048); err != nil { + b.Fatal(err) + } + } + }) +} + +// testPrimeReader feeds prime candidates from a text file, +// one per line in hex, to GenerateKey. +type testPrimeReader struct { + primes string +} + +func (r *testPrimeReader) Read(p []byte) (n int, err error) { + // Neutralize randutil.MaybeReadByte. + // + // DO NOT COPY this. We *will* break you. We can do this because we're + // in the standard library, and can update this along with the + // GenerateKey implementation if necessary. + // + // You have been warned. + if len(p) == 1 { + return 1, nil + } + + var line string + for line == "" || line[0] == '#' { + var ok bool + line, r.primes, ok = strings.Cut(r.primes, "\n") + if !ok { + return 0, io.EOF + } + } + b, err := hex.DecodeString(line) + if err != nil { + return 0, err + } + if len(p) != len(b) { + return 0, fmt.Errorf("unexpected read length: %d", len(p)) + } + copy(p, b) + return len(p), nil +} + type testEncryptOAEPMessage struct { in []byte seed []byte @@ -892,3 +1134,21 @@ var testEncryptOAEPData = []testEncryptOAEPStruct{ }, }, } + +func TestPSmallerThanQ(t *testing.T) { + // This key has a 256-bit P and a 257-bit Q. + k := parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOgIBAAJBAKj34GkxFhD90vcNLYLInFEX6Ppy1tPf9Cnzj4p4WGeKLs1Pt8Qu +KUpRKfFLfRYC9AIKjbJTWit+CqvjWYzvQwECAwEAAQJAIJLixBy2qpFoS4DSmoEm +o3qGy0t6z09AIJtH+5OeRV1be+N4cDYJKffGzDa88vQENZiRm0GRq6a+HPGQMd2k +TQIhAKMSvzIBnni7ot/OSie2TmJLY4SwTQAevXysE2RbFDYdAiEBCUEaRQnMnbp7 +9mxDXDf6AU0cN/RPBjb9qSHDcWZHGzUCIG2Es59z8ugGrDY+pxLQnwfotadxd+Uy +v/Ow5T0q5gIJAiEAyS4RaI9YG8EWx/2w0T67ZUVAw8eOMB6BIUg0Xcu+3okCIBOs +/5OiPgoTdSy7bcF9IGpSE8ZgGKzgYQVZeN97YE00 +-----END RSA TESTING KEY-----`)) + t.Setenv("GODEBUG", "rsa1024min=0") + if boring.Enabled { + t.Skip("BoringCrypto mode returns the wrong error from SignPSS") + } + testEverything(t, k) +} diff --git a/crypto/rsa/testdata/keygen2048.txt b/crypto/rsa/testdata/keygen2048.txt new file mode 100644 index 00000000000..31854020d75 --- /dev/null +++ b/crypto/rsa/testdata/keygen2048.txt @@ -0,0 +1,719 @@ +# Prime candidates for RSA 2048 key generation, one per line, in big endian hex. +# This file contains two primes, one of which is at the end of the file. +# The totients of the primes are coprime with 65537. +# +# The number of composites, the distribution of their small divisors, and the +# number of trailing zeros are all chosen to be representative of the expected +# average key generation run, to provide a useful benchmark target. +# +# https://c2sp.org/CCTV/keygen#rsa-key-generation-benchmark +# https://words.filippo.io/rsa-keygen-bench/ + +c3280c027a24d6e2277d1227e4531c1ee765bda9d304bfe7a59519bf2686fd5435c5e5a1200b74cba47c49f444e89b0e0991d05824119ee9dee73e4bd6ce3e93a10604239677fd0b735438b2360d0da9e6e929e1c564df0f0287eb0804cb9dba824a53156098ce8c8efdb8197d12ac040baef4e90710670aa7a33d9a0cd0c62d +d658a5dea2c73517326aba6bddc24b677d47178dc77dd584160827702d203908c504bcb305309c6ced76c7bb2f891bd99119e95bd3d90b1c25c00808c10f94e5ee29aa84d066baf7a17250328286a74173cee433292afec2e3707790d1d590b0ae8d667614a8ec33ed8cd9344dae48dff98631c7e609b7c63c4bb1a5dcdcfdb5 +e5ce50dd929f658d7285fa47a175298c0657dfcc98620e92772c6ed6134ba24d7703ce31d6a2e20e82b95be2a72f3818f7f2bad597bed7a8b5c6c3cf408fb49aa70c003182583a95b9c615ffff31343060c98b1058423387f52e3a7992a29b5b494a49256a7dccb25874f9109d7124ddb2c3e6f4430243439b605ba67a1c2f8d +d01fc442afdb8bd631d93d4531bb16f4f9c3bc710f6546c248f809987cb7878e8ab9dec73b7d3d823563e4df53e41830b16d25eb96985f393c17906caa24d5a8a8123439ecea4d34d7b28bc4f16bcdcbf1f2d3a8d53b5c26cb2d217c04a12f3a436510031901bb1af9c5530402384ca801dff5ab6ea922be78857d0290ae11bd +c0047306b9a1a51226ae3d77981ef08f43783f5ae6534ef5783e0044518e53a7c778759f88378970c1ac71e3a57a6f0839e45036d3dd180a713d962f701b139af22c8fe07ae2105c1b56efe0cdb4ef36e94d9b398570db68efe873ccac75186357ffdb5f9e10470e62efd78b09ae76508ddef6c43faeff84cbf8ceef9138e035 +fdac5080d27a1a4213ee721dc344e16b5e8e6bb790e1bb8dc965a2e76b2311889fbaa9967b57d323aaf13e2960dedac6ac719a1a85a6817262703606b176bf3675922502040273ce256939000801cd1dd8888251c14b6223dd572d4c9efee5b522b2a06b0ccb34d302524eacf1f9183350c90adf8f5ccdaf708937f25677817d +c4876a812cbb5fdb31dd80e04656a0bd3e131a2d2eed4b29420f373e9e4ac61a0d0a023713c030bcef917c146647f97aa9937626f251f1fe2eb4106f3eeecb6b8c2346ddc9bd88740e2115b23b72d2d4a4ece93f96ec34b983c61cce8c33bb650107859190c2bfb24b326a534aa0f44fc2210601f39c82b344e184632d825315 +ecfd96ea0fdf3cd7072d6db2d9ae052f50a16b948838353f9d566c383309fcc1e43d3a0ed9cdb9c9d4b0d8552053a1c2561c7df175bae082128c3d380a60c8c578b51049928d0669bc2f20256b80b089f217f390c80252c49038bd1f2f89b265d49b935c5d621a7f9e6b41e8c7c5e454c5b539f90bfd2e5e09ff19ae280c92b5 +d934a84e3d322798b83c86259f93f06f9545a2d5cb911ce4ee19fa887e433baaf6cd3c66285626dc09669b4b2209926193af341683629bc8575f0d3cdff3b558566733aa3e256f4363f4eb4005caf7cef91d2653e20f7b2c35a74411dd73e8be0d1193f0bdfef5f39b680d069d64b3c49de3d31e91e19015b3e14e24884010d5 +dd1f0316593bb2e1df22f1fd618d56e7c4f28d6a85501ce14e262dd316acfdc67d17caaa3d7fbb730c885ef394050eb80ce597cde2510153e67d99ab8c463f6b8d3aa607e49d8303318f9c379df7f48454b9b1093ff29f0a6e78f586d00f26912b2f27db810b96c956586ebafcbee500a701f74cdc42201aabc2c5a1977671ed +e1eda3a00453828b2060ac037e3fdc546a019c30d7ef08c51ec722ef98313148b08583fc495746ab3e6a46efb4f4342013ef44da8821adcde73bfc873b7a521dee1e9cccf3f169e78fba89963a4561fc507c5333befa509cd910ed26e45c62a2a3e0df1d961042e6f38474a99c9c5b366d0a6d81c41774d1ffc4117cb9f000bd +f04402a78861bdb7100df31330193151688bd1c4ecbff887c1e484d67ec705cc62013d49f1b92fef400d5530202dcb4145828a9f657d2a1c454dafcb3b36a1664027ff703d78fbf4712fc6248308b56ca80bd10b19263df5194a74278269b61f5199390d4f77a9934cb88272681a77682dca4af9cdbcf376ab7660b9f3e6007d +faba6e112b7f349d92bba5f80de2437ad692922a33efed347579eb7be667b1df09a2dcdfac534fee0fbd4fef0838a74006dbcba62b8ce6cc0e6d1e1035effa096085716e4761083728f923525c9ac4339d15cbce8164d2abacaf1e134802e28733d1f7e7327f7430f4386102915f02b9c435b7a4f8a0433062973356490c999d +cd1d62358df14d823c9aaef80de713db2bff6dc3f15da163f981601b2096cbbc04ee12767937ff5f7218b758defc27912cbcfd8a7bdffa48e1c5d4accd21ded2cbb99f053103555cd78e9cbe0ce6e89db7fea4718b326f266c62ca997c1102ad9c04a3296405d2f9b8ed4a0e799e4818eba66247c25da68955f03f076dd7f735 +e4ce1badc198ea490b37dc7c04e6748904868129bb8cd4a7638f5cd9b7cc5e7f6f92639faa0bd755c6b84bb8c8361c5869b248ec443b24a81e5a9abf94309653f9777dca00aed9fcecc21dad79f9aa5b1a720d3800728a452d5a4fd4dcf156c20fcbba7e0a10c5c3cc63bd6e24fa63b248ed1a9b24205a801be3c1cb74be2bed +e6212b34639e14987d4820c32930bb2a72ec98670dd8269ffb85583f86be8152b6421798e6f11f64c410966f5fc85074b932944675c1d2e67ef1e831f15cec8dd2b8f7635e84c1624cc830fcf3ce1df011dcf133bb636e2a5c92789bf6e824a0a84c9311d0903af0ccc2ee417400538b745190546f97abb03461efcd924af65d +e64458a6209dfa4288e20607c5efa3ef0023005dd04286bd9d97e835e6316c8b76a6cd471d74d30fae6f84a0605135d85d5b626a9bda82ff24c1245428be2ab06ed0fe994f6bd4189e5620d88dfafb454dcee861b2cdf7362bbc4d2adafd606c17088f190e6bd14d57b51fcb1068b13cef8c454e138694f06138dc7b082dcdad +c0896f1090bcc0994a8888a71d7aa6a484d4a02312a2fffa805bce038a98064f054e097488c9e2e3f8daed458cca270761d07daeab428591d6bc30debf0548949ab2c89b2a4950241f78798100efe858b7667842410091764b6f62061c22e1b2f923de098547632f81525ed7696808097d20c7703b6ae01e11c094aee01a39cd +fe882662e021d8b4329b80e6caacc66174c483c453881389de36331a81b229c8404b4916a8103139fb125289a3746e3ef11370b6453b170635b727e88f3ba7ff760db3d69b87a6613f41a6a0d2af65326b109d6b4fb940b3dd20f1920bf40b88bd6027a11e9bd7e6e1508ca1c45d5011e084085aba7898c439aa9fff2466cf75 +e87cb70f7bba008257d76ae1b6629a6a21d12158eef819d8422a8b4f18830d426d784ee64d204fbbe3d21fc6bcfcb946a08b72e92132563de4f52c7e6682785408b0f612d7a461f413b68a186c637872a6207aaeb3774d302053375b1ea36bc63a968eccbb6034d408d4fd82c93810bd50990d28b5ca037fb541cc0402770a65 +c59ce336ad22514ff1bfcb64706d7812f8fb592fada9adac89b7b4bc74cc100bb7d41f6448a4fe8e8c54ad3eb9f643ff62240f1f24e4f7869c4de12cc7530f8856f5abbbc098a09a0b6f98dbf008ee586eed521b608302c49ff5450117babdcc89c1e1868503557696b7ea13ac4587d1535982cd0d88aac6161bbd3338877785 +d8f6e37189f694e33286bf6489fa969c0b82e21fa3a7fcdd142070bcc05a43b89b55163db9077a3576cb8917c30a3a66a04262e6d065cd5e74a6064de059c502c768edc7e33647f66ab6fd024d3c900b552dfb6c2d6aa21b6c1b569ae31bd75b2bc4d968ae9c49009c770f57d121a9c3ff0ed376f424891e734456bf605a943d +dd66fb98c6b659ed158375316e61785260961deda5c7cd3a620c21da10382f4aa97d02c1107bfa0589fe6362bb883f48dd5ece326f3c7cbc28d91ab7d1fa8ea1a0df6704bf3dfe9b1f053e4e307d5bed6bb7576254a8188f1d60d91963dcc2db5f7723ebfba4adcef5c5de4e56484306da72669305e167fd2224e678edb0c5a5 +c5a1245c78e99291db45c225773d2141b204c9c8627dd8120c4cc331a67c0b2c118e20dd7805436b4f05b36ad6b1d20b128286976e8f61772f2635ff88fb1c1f6ac2f390175eb9f4f556babe6aa1b2be9683ed442261a79789b10c5ab0f91eef7cc7d6b99d0fccf0d8a9780e540a3ece093ce6dcbfe8e62bce995c23ff201c65 +cb8ca7cd1d043349c6b244ea7f7766f717daf97fe5db079c9f94c0a30ee9b7fd6999728fa22802ac02c7e3228b53030956d3a7c6c148620461adc434388eb9b90ddc84bfd6032069a425521548c2cb78b4683c80d2c48c6df5e831fc23731957d490193f15607c396f62ad650c4266b8bd46b0127001b7d36b97e3b0f76ad735 +e89e37f2ae5007402036195b40ebd882f60756b616a827a3267a701cb12a7000723ba42eda4619989a8d080a444e5a8a8d4fd1a635279297f420e20d9e2587391613c9c35c0e4f6135f5c3abed32fe28783e05a2e0253e7bc351e20c4ddb399aa24ebd971fcf9db2263b0d01b628e87650d14cafe341f881b010089052bde375 +ecc17a8b65380f0203aad09dc6fb76d31fbf9d75a2e342a6b8bbd80585f649d1c1fb6ab5db10e2c15353c9baf32730ea797c9743a8e64e5ec31dfd776b0a25b2b80b68ecd612211b90233f2662381eba397fe5b2bd2cf330c1c7a3abaeca21a13ee088a8e24175022df26221de4cbe1357ae6cb0c93e973779c5b23c8707759d +cc377422aa2d5b267df8adeb9e774012bd8ab7e86855deb61466882d7ee02a749426d242d3329ed6a0b98ce56caff22b2a2ec5c1d7565bc7ac1062b3c9bb887184d690a4c39987e706c9b0360a9195bae763ecd9cb4863b7020972aea212df48374bac14101073af8169f8113debe9480af26dbe534ff7ebc078a84fea0452dd +f6b8e7c33db4bf1106731a54905cc34ebb8235ef9c8196ae9a43afc58f9fc478cf45924130526d2b3721cd9e5397665159d9e978676ac5663838bee9db236e389ff21786737b78abb5c34dd44f878a6a8f38b4f9017a8429e0ff7efc7e95783d532681bbb652222e604492e5e9cae70acff964a27274e30f3544758a60603c85 +f45323a64eb82a494ddf732502daf879938c2000b2f68690b013cb3a40d7459d850c41c829fb0d830a8a8ce53e43040c0e2de84e36c8adcf8b2935fc4d603d5065b7530baa21f3fc8566d13f6840dc0000e0531819c833ddb9db52257b1b18d815adf7f2cc1a74a8a2417db14f3578582987324ea66a85d6877e2803df34976d +c4b49ac4794fcad37ffeddf43b27b0f95d504ebd8faec1640fb3d1ec3ecf0d5f433e53f62b436a17436104fd1368903e38a10e173267b2105bfe5f64be5c275f3e1574cd2bc46435b004c158df4eb0ea47d3244a16e2d4eb49b68f06212c3753ba6acb74e59ad0154509ad46491b167f68c118f2ab8ea351f22cf23946b98545 +d9966e5ef2c98ed3ab7665493cb3b29e0b55e4f3593218417dc012d0cb6293a3ec9440f2959f3990afd04def8fd14e016d949c0ae116900fbd3e810addc5545db1285f73927c7828eac881a6bb5c25410ed7a9b28e9bc3a6e96f1a239dfbe2e9db90df2cc1bd832293f06e30b4cebf795945b717ec0d273364fd603a2db06b5d +e0fcd8c3c66391647f3cad90bc667361230cd0907a4f95d63b85dd7ce259952784a2facfd8a707dd58c5a66f1f3f238fd55f6c39a615547448d01ed27c046357edf1c7c8efb17e529a9a28b63e83aa0d203cc687cbfe19201388ca4edfc302fa04e11dca78907ee5401bca9b9ad1650ae8dcd63921aacd3afafe39cc9fc0e18d +c2e60320538adaf01aad0431695c391db850f09bdcd1d7711224ff6117e966c3ff1df74fe32210f805dfe5b9ede44b3f5b4398ba09f41712a0acfd17d3f29d901531870079a2106331127a4ee083b348ae34eb10be594f24f320315535cdaaf40ae6c0a3ed762e5f4f77aa6ccd01a1a8a471e2790210485bfb2179f1b214157d +cf2bea1f18b8b7c173139634d3a75be5b16cb92c08fd01189a75d214a0467380b64eaadc717871926d76a3dbf60c488cb1555eccdf749bb161c6f55bf68c6bce9e89ca4d4165cfeea41e5d7ca0bec8b5e32fe8a4f433a0b94e34949dd60f3a73e108ab3ed1cca9f1bca7a28f111ed8ca5b88253df61d7921d1e53de8839cd4d5 +d846b3f003220a8c32229f05a7cbca5fa373ac6d5b6dc3cc2bca8f0c1ed73092087cff694c43ef25b00e16b3327127259e48c51ac271faf2c6c8d4745f07a08b4df84aeaa95d0a73ede4eb50264198625f39917ca61787e8441f579e75a370a11b51db89851783daf44cc88142af0c558f346ee033317235085a2cd185e0e5cd +c82518eb29d04d44fc4d8ed9cdf5252652db5214be69172f58ebba11ecf8ccbdc76e45054484b270b559aed27f66c97f105b997e83f969d2b8045fc5c4795a0f14aa2f26d66a376245ecc3ba39dfa105044754ca7ed6b96722963168f565f192e40fa1f0bd4c875d325394eb72c13f53af85814aed81db2ccdc76feb4bdfcacd +cd174cce3c2a5a2aa08ed861ad64fb0c6a03407ee93ed2343676f1cafc25193af66589d891a1aac648b4d309b047ff6b116dc7bd974acde138cb95c4d7ee95737aad0742aa8d1a9e1781b7cf2a6f09495eb22d2767412a6743f2d80dbe8ec2b07ff4ea528c13e66a6f90385975f8d441aba9c0db2085b7714e07636914878655 +fdd7dbf9cec219fc1c59527f14b95b1094107a0173afd4435582319719f86d300c59fe8e676e29c4b90953208683694ac537b1bada7696767e0fb69893c102da2ad292318a8c06623844d2baf98ce5cbb8f5f4aac2b8adf1ba6cfb0b0238816d76f48671a0bd1aa42ebddcb5ca36bdc6b163f2fdf808ab06ce8129c88a34a29d +fa040fe20e7648d5452eb22d0449d909131d8aca9afb85d969c029525f06d97c719b5427f767b0c64374a0e85059287903827bf981af82b073909ecc277085e1bd489d8416f5e78584565fac47a39551991fcd6850d3705948630b4777eab04ec4d8211bc174b4f52a02aaf3176817c461aa64c0cc6f8caa83c2dae9785413f5 +eda819394c12ddfad1c5195f590389019ccebdceb5d22bdf8f0b8039f339cfa920726ae970d02788062f05e3f94601f6cc73caa1385d12e26842e8658c4feb352a77fe30cbe16475919ed604306151ff9519500547f02c5baf6d0ffc28c145eb09b64b6513bcc006cffa11b1ce9550eaaca8b52abab2731f0a87c2cb3838bbfd +e0a102fad6c51e75f45f919ff5c994fbedbc2decb9be980fb643c5dc4e8d7715642daa68e907ef73d50f48d9b22f9dd269b587edb7daf5086bf9d524de5b0ced07ec6ddcdbb6a7b80a2811a041b43d80ef92d80d26f626712921b2f454b16f9ce469979f9020058df410a8c0fa58f79a1ab8909258d136ea7565cce3db5583b5 +e29cac64588f2d390d569480051aa315a28651b17b5debe2f11937c590f7a6acf553bfd700d56ca0e9557e0002f8078e5c459dcd68621a7684938324207e686d5641210d9c25030892671e28dddbbfb8a5592162a9988e6201916cde8d4c19469edcbf2d539c9d13225ed75642edaf5a5a41f70498f6ad7bcce75521c56ec055 +c8f655d328cd97dddb6eb73dae1c513547e1f9eb924c9d3ab85c12e93f55e7585bd78605483a941d93c951ecb7703f70acfd134898f2d8c3b2eb852694feb12a536b68b1b31df677bcbc1818d00cec3ec77c69dfba074b773458fb688d166147942c76d2e90fe3bf6b1c63062bfa85591216a3a9a1fa89762c1c9d0941c1c5f5 +e4e8eb15317afd379b4739eef0e964d365f45e52838aae4c04671bc51ab06aa583fe7efa805f3beba9bd6c94d9cf1c4816d1d30a6cd0603d8e9e08d367125e6d70b3d1f4bac36d2d81442136d06bdb68618a895ecf5a45d27c9bab3f5302bf93c770680fb74d79fc3ebb0cb23c70a2c798b30e4341bfeb0ae224d9adee129aad +e9b15d8bc80ca4b280c5ff6ee0c92de7efe5d70c356855de5e23fbc6d7c3fbb9ebb2018cc8d3c82ec24ea057005aeb8504d68579c13aaa90adcb5719b8cc633e19ff70ed00f5ea38230eee0fb6c0185ad5a946798b8477e5e0a40961891ca48da0e92db23ee17549212cb337094a9074759544226d88b6a4ad0795f97adad15d +d7a679cb982749b84280e8e68593a578b1df3c3f3cea32c5f85cb8ad9e916a2e46804709b7d13ba3fedafcd5363eed258513077f8618c187a5ead4d80e365afd07ca9b94790e9ff312b7fbfa363571cbed16f7ecbc4958c56d8d2834a80841d55d200fbdd68d6f2edfd53ad9bd98b87467bb33f75fbf679805c691892180f6b5 +cc223cfc403e44f7b1b6b1b4923f5e601174288ebb449c591c7acd53629fd1d54e713a06f3f0c5bae6e0ec6c60f63a39628ad674607ebde06ded53451758cd3f46a2804625ccb5c6b4b8d3387863ff0f191f241ebc76ef2c002ae25415844b968887f5afc058a8a84a73c00708956bb108e22afc824481bc5f635ceb5b612df5 +c8cebb9900596d86f78b675e0b9b6e2efa078d5338e2e8c411b686eaf9fdf2009b0ddc390a54f9ed042363a55faaf61b1db8f81138701bec4ed242a96116111baa7a3a1a58f290ead2dfac414451ca6349b40a006cdaf8a7279413b774da1ec860e60d4cf8bd496c4daf6d67a071672b5813ed77e8cdc39463bbe9e833fc80b5 +ff877d7617c7692de75b95c6aa2b938e06917fe3964679d4d99909571a4aea438d5d9d749ea1cfe9edc3ea5ecaeb2cbf67df63e1d77f2e99841d52401fab7dc8dc8e7db0bb4bab56c2a738c0567fdd9e1d5cad05f143d9a208f1d3c261e2ea1fafb523e45b7ba00d3aa14f8d0ea6843f978289988325b778a74a503afc03dc75 +cdcbd7112b042912bd54805d11c334564f5b49da681c0300afbbf0657f50655b73775b8494160160c721758f848b8f5fdce80accbff0a819779a3ea8a081d2c8204e1ffe325bb2bb20646a3e99e0afb359fac49747724d30fb2861d4fa3576e157ea7ca9a5f8acf8d978a680cf20eac31c46ce888214306d279257c61372182d +cc8bfc877a0f189775fd8663bdda40e940dede0b46a834cb46e57e08ee7ee103275eda18677b67a7d15aefb25311e15bbb8320c72794426976af19f61709b596318d6a181afdbdce9f663e48da148de140c099b10cd8ad5c56befe57b612a3543ca80ae0b1828da26f30498d4b685d3a3bf0d9821aee4eeff19dcd095312861d +f57c84d6f79dabd40b86d9abb9b211355dee5a80404a0858450122d5c9b7f8850aa9399fbe271fd3d551b3fc5cb1f965e9f7ef04d725f8be2fa1473bd2925541b006934939bbb4cc6a061b12c9c4b2b6c3e72c05c9ec303ed089e71cc33b7954004cf5ea29c43dc207da28ce80feb805c804a371adde587970c4a6eb4c1b04c5 +d1be804b2c5442d6f2b8a6410d7b499e8a992a72fa4d532f9715f3c24abc6be301d5eeb7156d8b2010b0b61978ae0bc4205b3b9fff4d0bcc9842d43ee99b56d741d7c06b70b9928f9455802e6b714d01622ad14112f78ced761f10393fdba4e27626638c5b578da4db161f3e4d52edd897cf0dca2c83f1bca4422af1325fc82d +c3e6cc9373a12a14d3916be237b0b016fe7f240c9e7c631e50d2078d63552a898c781d5c1d23d4a4d4881ec211af661527fac39d5937e9f84bdb8182e69fce9a2a31618480bc538cc14e3d778cb0b7b3ba5ff2e4ca04282bda5df1333ed840e437b2ba8daa1679b4288f95ea19b5051ee77fc0dffbeed396df58796803b7eb95 +d36abf4625822935c2e14f94141ac1ab6a700f62010d9d5fb56ec9d582fe5e8ccbbace8496b16c215575df4692fdb5e5603cf0ca4680d9cc2e9440896221c86c0d3d7a96dba443d2eb651e95326d2663d8777c724c8b75be3e3b2319b23ee3561748560be33e8e4fafe01b40490732ff991a7c0f971672fa60f7adb59ecc3475 +ed3d82f546fb076502e0f5c4db6089fd203a6f8cfb7a3000e8c0d98ca15fdc784c4ffe0331bbf753663f7754c52886c6175465114a0d009829843629dea455d6ca5e940d88e1fbddab15ba018ae467a7bb2ac7fd9df12707611134a10e6b008f52bb0d2c3889a9b6dd8695fb7287bd2644d38094222df4b6e0a3799d95a32cd5 +e9faa255b3a1b7a6514cf14b7a62fa3ef57c1e7c62943aabc0ae690ed22c656d7477e17a42bd104e4243909576d03f93805c50873b8af7b6ad4a67350842c84ef4fff257d7c7b21dea8a907bf2be9bfa7261dcb50cb6d80ac1ee9e045027d0d6c4760541cbec65db502eac75e340555b2607779fbd4550218c0b8f8303692e5d +c3995bb359e84240b30d6927e9999a3c8c31577b42dbd527dea888466f209724156f57b3392566ea36066eb321924d8bdc5868c6a3fd546c413f31a3a85e8cde6977c4253af146c8acdafd179a5f0356d6219f3db83d565ce1c1286b5083b9226c982641ffbd5cf76738eac94b55ff7ff37817afc68761499762525ac97d8b05 +df98867af5ade57a001271bed2114f69b037ce084870e224d7b0b0e1af1f911bd91e50cfb6017706bf027c0031ebf403420690dd73ea6b862ad2340a1281063a52c647e793d852ee7d610de95d8eb418c9d091e8651f8a9f4c2becd70ee006abdd439e38a773373ed57210044143472bac3ab9d587b84ea9d166f61b9c91c1ad +d799dc56a7286200cfc1959e434161e67551f5b74a92e515466ab1332df4332b9e07af5803cfdd4aea7e6b76f24049cf402fabbdb4529c180d63b1fba3badb09b23eae4bc8784baf2487236b94684663e3bde39acd41c875ebdf1e5143a55fd15be61b2991bc24f9fed25d9779c75176f597755f6f0d2a95211f4756c1516fb5 +c6310962a28f5ef6bbae4ad219aaed7a5fd3021b64ef4f92b3c0ecd605cad3a9f97c8a8019724432318b1e65452a95b3e8a91d2fcd4a0a72fe084cee5c526b4ffb8ce02e2a394fc1dd4c4781aa06be5c2e55ed015c15c4f4b7c408af2ecabaa3b2909b427960571eb7cbbd9bb18a9751b6a92935d41e9f7176c97b64ed55354d +e5192872a3d1e009df8a07cfb29361e86c95183d9702d02d257bb5bbec7830e44f14ca100ba2a59fb3dec712ff6c274f592a45daac1e5c2b4e31b737ff1a57ac338e4e3fac6dac68671e3b7a6d5ee21cfd8604c04bed23a45c00ea0b7d0d1f122af3229ca667ee8808f86fe2e740c016729ca1082873f71ec822f145d9b76aa5 +e44d270ef565b5e7e27244463c6ff3bfaca373f5248970a917e3c76f80f274f328793273323bcc30f8779dfa3454787931c7f7a21ebf41b8532b8d7dc86c1f67edd627e7425aa3b86b3f865c848a8c5941ee098caa2f307436e886983552c6aef44c25d65186e1d0ca31d32a9f784a7e9d42d704c331cb4bf2815c084b356315 +e0edc4ddc48bfbd3d7509a7a9aac58c5538218b81f4c3eaab6fa616954c1d19458271a91925dd6a2da62cf33fc137687c3027fbd671d8c272d4d74e4afd343530e9a62a90de771d7340cb3acaf85444c3a861b7f73f0f1194d9f1bc72482b7926348d41ddc5d74286349cd7570fcff35521f0747ec8d3cee3d6ffafd61402c4d +cd5729475237d63b4dba8e30ebb93d68a0a867e2e4b7d624117adb20708c61102b0ddd4fc2c14001ec81fa9638f6bab94afd4ed51b3dc669ed3aa800b6b9c52a396f93a24b0715dbe17a1a8ed2d773c373570a415647794b28a9e4fd450a6a3f4e6af36dbf31201f194ccd6b09905982e01d5e56a743f4507645b84a28435b75 +f629fb24dc8ead8c4fd6b2a95c080d547d158c17f19ab53deb4eefe36857a5a1ade5fa87db6928a3b0b1cf9dad51819d93f4ae71d3881a26e54cbb10216a63687f2a6dee8ef58cf6d8602b8b394e6b9495874b8f92aa88e2edd842ca9174290c411f7e582ec2a691968ccec291d849d3f2d0834aae803b77839bcdf42f3bc97d +f8b09d6e5cee1df04800701b4583c8b963e34224d6c9566bfd83b11afe5d8b1b26255918ea42df2c389f5c355476ae841391282399de66a055d02bcf1cc71e1b22d1903e4dcbe0bdeb478a9949690cd694fb86ba6d7e83ed73e7a739486d5219cdb38a7781a5144476f01818db6abd1d73be57b0355231f24ea0154c20f5050d +f4163ed4e0ddf79fd97c43604c8e7b0ee09580b62166b6735c55ff4fd849c938716c0d129f5874dbe070724a0e4186a9a196677e1a7c52b9f34a117d51fb97281446ff7f3336b225ed287e4dd82b84c024e88047292d18e061dee2f7a9ec5a8f81a7717071a2f86bd53b80f68243bdf19e446232951265c065a60fdd487b7c3d +e1145d235521795fbcecf10eb4ca8a29cbeebad436d82540ab3eac21b46f46891772b08a7e69b1ea1c504047b0f584b47c600e18a6d7511715048c4e68a6c54e1af0ded19d84c83f84aadc1bf6ba030f2f80afe29adb094eb68a76e8cc9c8caa95e51c11fc590c90aa86945456b72324cf7035d13e4a1ea7f39cd265964e2ac5 +f0f245183e09ce283c77f3e17e0cb4ceebf99c23e4433a1241a68829f0709cd929068f8984b0bef578198ac06f3a3a753697695447d0a675d7a897ead5a99ddc0a444b4e6eb568932886ae1cc3a67647a248a3ac95e941517da3a20e9bb301102bf28d812434358035901eb99568b8982ef9a76cea58e874c686b9d1bb7e6cb5 +ea13168958667f214be4cf775d29789ca2851c20360aa05e76b5caa7d1ea4e6208ebaaef15dc9eb2b0cf54a9211bc0d615c72d251f361f861d0edfcdacc8c8a71cdcde40baa97d8febb5220fc253b53759b208a6905e00ee4970334270777dccfef096274fffe21699a37a187d4e771dc33d21c8a39e479b1ae4e820561aa5c5 +e666c27528aeebef0bcabad66873b3b44385315ec52177a68d6ad4fe86eb0307ec0aee39d7e671e8dfe432e31ae226cd99e3c3af73b9740de75674621abe63a510b264c2d6597e0963be2257130cdc4c510ac5001370b22d7edb060619dc525380b97787853a80f51492e7d75285a106d4b1f386593b4a8deb46baac39acb12d +dcb4379101c0d50c12a85f4efa5e8d5a3765de6f646060458db7469cd2fe0ebf620d38c64b0a6720080df8859ac74d3a5209e9a59e1c2437860b58a0ff8d88c279b164ff5f817612475cab07c966b275647cc3b765347c21b431a690765afa60f0158da8101214f28d034318a86bf9b592cef2abaae616017e2d5a046edb752d +ea5dab735eb313fae23a38a2aa217c62cd7d67a00a5a56fea73ad5ddd38c4668ad89a4cab1f94f3aeaa1ae7edb27518026e41111b513a74a4d88b3ee9df0bcd991e8adabe8ad233b0fc0bff82d0c87f010314e8a069af98b2d6aa922a8e7792e8a07fd61da0f8325fad04daedde33ad9558e193eeea4bf35a73ad21995f02c55 +c189d07afc0ff09ed9fa600f2b16bc6ade9a253420079dcdc5107946ab42e42a00b2728b4baa608f6ae6376b2c7eab0b15824efc1f9c5eb320f42c837524bc9979322fb29458d40dd65c5c1e629170827876dbf1f37e774d71225ac3a548f4e8126add70d76d6bc802f84484aa402a0dd379f7ea2c9a9d5488bf26c38b46267d +d74d8e36181e5ac15aa040c54bf8e64386aad135468efbcc1cb17c9db0da80a233ee78cbb83c8411c7632955e1e5c151b5631d1bc32683975c9db251e3c8eb3336e7bd888c9607795e040b1eeb85a59180371f7089f9f19e66073a32af1d9c23004cb656eb37955b4672ba85fd707934d0018202d02af9a292fdc537d9335add +eeedecf01b04430f99072f20643d57b88bc4b3d1ab69ae1db4b1867ba7ed56d50fd9ec9f06be6acc702b2ca193147343483c83f77894d98af2f36e6695505ac43c9cce9a6fecc94fcecaa89360bf407b28b6332db5dc5449ea9c68b227ff1abe73a612e4df4632a5d8dff54d721671ceb603ce0750e2ee8ffa2f7b82b3faa015 +db4ffa9ff038ad29458284e3137601bca912bc18344cba7385c3fc73d2d072fbd0942fcd9048321d37ad8c7c1cac6b431c87624639859685302dc830d671e7189a64d3fea5461dacc06ea617a037af08845f86b2907fa3bf7d2308806694c44ef29002a735b58802200391c3a2ab88ac9cf8ec437fb8068902160534788ad4d5 +f49318745e60ce9c01a772f6c051f1b9fd0c1218ef56a442ab235d6e7c6eddd21a564b22f1d587222bc4fd062e668d24b17802da698e2364720a7c1675fb7982972f7cb583eb4deac0baa2d74ebe3759517e9823bbe50bcc3bd94d7b175928f268d95e68e734c6a7e7c9e14b52afc3d2745b4af669f1bf436793cb08a1d5acad +d2fb4ef724dbf7fcddd0ba8686c697f5c64a869c70efc258cfcbecb68e0bd27c5269018b957604f4adc46124e28078a40b410d2b6fedae4f91892d172204327cb4e71f9c6f89b2d2b23f1c40b7389205471358e89db6851829f9b9fdf6f7736dad4ccec19830e38f4f5f4dc5ea9ddf3e26cce3cadc2cfb30752682e4a829ab75 +d5daa77d5cf5869c9c83f3048a11ad7cb39aa6ab44b353c9b7d5a4121aba52954fef42bbd60d475f361af181322f0919b9b1d82339dffb7eb74cd800e1ed8f71aacc66b6fa67613e82e40f522e662fc27604e129ca42c311e4994711e143459d21c89e07a7d14c02a85abbdbf2e32f9b559d9f24a27a98b2521d39acd6c690b5 +eafcb4e1299d16e398fa574e354d79cdb9625797688faefaac2d4a29b23ef552823c7e19d22fef28e2c1a24c6bfa374063ee99fb069b97f8bc472af6d69ced556f13efea086266bdff71c1b4da8e4b3f85e1a72fcf562a70f198c7608328c9277d85247311acc83a98866a521b7fb9aa0a7f4043109746274b624d8dbefd4745 +c7e8eb5f561d14193634b83e7944b8149e67f8bef30702c3a04acff906d4481134d4755317cfbdc39043dfa9d7b4c0f98e5b01a4f50ef49c7d17ad7c4164d1bd9a504de03bd419b33980cb0d0938f0e6aef5a7e69c1da4a31b4e8398eb00208f0175bd1c4f46e4496580dfc26bd9ed2715a9672e144e07e49f44e91f68a0b8bd +f08ec66071a5b495fa35b81ebc06eaf3fcfeacb3fd78b753e5de57cdeee8be92bb77db13d1b62490f29e6c1821e54cd30d83b54cd9e9eefc349c7cb4333b67e692fd459ed9f2591166693dda538bc39084ddf85014a38b4df0e88350ced2cceab85fc2be8b14888889f7c2d5e9683674f40610855d77ea09f89d705ca753702d +c2140c54f9dbf6e1f412a27fb4d6c11b58434a1ece009dd1dd820ef05f59dc0da64f05d96be8b9d2b27c6f9f5e49cbccba9b16fe1babf5eee02fe432ad86c04182371d3514a36f416197b9524203c2919b2c79ad55467ecaa56095e3048830b63ccec9efe120272b6ed318804cdad84a62f99bb63464981f552c655babf51435 +d4b69020109685911be78c377d4bd7fec5443a91ea13266a0c8286b0f1289b6df4b3d451ae92c5dfc1c60c9ef38a381ec9257b65f984e1e364e6c060198f3e0823405aa93abd8ddb7daddbd1e467df6b7b749fb31e4edf88fef8d222de401a42bc180fc5c5dda9d7a494c8c88359072381727a59a3ee715035441595e622edc5 +d2b5c8d40f92c7f7af2933c5e7a120977d26637932c98ab9b034c53074ea38ed1279e7e71b062b8d140e3d499f96a2cf696980043611ce272475099dff5002bde2c6f9c936b4764e0adaeb84ac9554f81b8de3e195a56d9314660d6ec76438d6ed9c8a84a2cd1d08c50ca5d12392df85ccf70467ea0407a3985dbbee5293ce7d +d2cccb950749662ae7599688015675cbbbcf7966a03d22dc8af81f4258a1b78e9b9d7bf8b5d6983256a98af801721a139df8cfdcd29e576af1634a7c682e016acdb7a510d058d4514be5b50e733cb9d30c7b0bb33ea184a00f8b3871c72ae3bbb37d9238e2988fbbbce08c2d4a065d0c63e80c7cf40f15535eb55e4f50d360b5 +e81853fbc8f1fd6896a47a6e80539439cd9645e8b0ded1f5c554cf853e617bc0b411d15ca04bb9b22fabd4aa2226df4c119d59ce36ab116166dcaf03129c94f7db155e8638c8d309bfcd64fab7c77e6a35b3d2668a40f02618820f51a5ff241c8887066a45ff2fd930e1d5a6a18e9e9351adfa05dd462dc7c9382fc7494b54b5 +de9f654dde79f9170defd2ad8386a4ab535889fcefc088eeb1addf4aa45a01a0a4d583e40109a9637aaa8c7fcd5314570bef2ff3b8958e80f2fc146c71b3fd79ccd4d06d0a7be94eac5ccb5fd44695df6d78ee4dc7a9a6c51852b95219b9b296a10d5ddffb8f38ac5034351565caadc01881d3575709a0e9e818151852816bed +f89cae294cee1cceaf47188aaacab9ef8e42b584dc85456f370aa6d729e28d018da252093e35c555f242c44c40e1e531dc1f1fb4fc955ef4dcbb13a340adf0c7101e1afd8d11cc65993fe209ea8886855c132b6fc257e4190356375cb8bc004598415f51cf5d952707e42ac26c85c184990906c26f9215b9353a22cb82e2acbd +fa89c077b8fd463079fbb1c9c89b2891e6afc11380297be421cb5a7ff390385686879041f70358f1db73ebc8df6a494393f0303e5c560a3fa2aba714395a20398aa953dca5fde0d901e1bb617790e1f0094203b5b1ab164d86783955e5826fc803cb72c3c6bc77ee9477d3eb7df476e6df97a4b20e59facf160c2ad0f35beb95 +ebfc6e1f84e61274faaf64e51d06e188c3efad1947ba41027041b56e3a1c80dd71281759d7a75ec704e22d9e205673ad6a38f0fa0d936cac6e3c2754b1f0f12946f4ac36f3248880e2d7f57635e80cc27c12b8016864d02a04e5236f537eba37f7d4fc5b46af2d042702110c9f1ece18d74879f776e3b21bf76adcc8617e8fed +de9ad428d3d9b64ed58c7b59ae9fce61cb2c5ec3f95b5955341f67ce61c0db17394fbe596b5ed306a293c2ec9591b5f5bcea5b396bddbbf56f435edc1b4484de6310975688210197160c945b7ee3ebf6b7c9848318be0e45899d364fc67d4ffea82479fd5f672f8df5f89ba157ff7ce6953e9ecc685b5f50f629de639f372a7d +c87d59cbe55203e3b5ea1bee1489173612a0e52d9c366a7e09a0575b0e79ff5d07f3adcc468018a2ca24b974025d2b26220c2a110537de158dcdaf860e8e7e1685e47f8327ce81ad8244385c88c477add2c8b997b3014ffa32a952e179acebd87fa545e91d5a56d4a16e41e50ed5e3d5dbbbd7be870944b2984afc2d57607db5 +d82c4ed9f5670b8b68d2ad054794f78a0b3fdb32e88db4f72f75033983bd1884fa8bf5b3a1427805b2f4d4787b6a1547876a01c8a9c2c74799d5f7c6e0f0482967c02db243be59c78e4fa4f5a34e4895a07ffcca0ec3bd5f24048d10ec4e1bec3945d7280d8144b5672a76746f6c15e42970eb55c840687a915a464cf4b4795d +d500a754e5fad4d58a926c0d18159eade6b51ec72a6445cb782a9954c54176bd7d70d3a60fe5279757a739e6062eb9cfa83e3520e1964f59def2d9808b32da1468af321ba7be5a3bc619b5c75c636efaa86d360e8fa0675f3dcdc4438c417bb51902c9d3565e37c799fab1b94f17854ca143533795ebbcc614bca54f36959c4d +d4d9363f9db9a5e0bc14649810f5c435a731f6a3fffe42b24d8df6a6eedd5ad0562f17be5db9950d46407bb9dbba9f9a3ae29fe3cd6f8d04595ea26849bd35d49ee0e8359c47cf5776b51567c82ac6cef6bec5fc4e1d5f5e712a1a9e8b449e6a577a4104b385bbefeab0fa580ad8b5fe8712779b5391635f8fec655c59d656f5 +cfbd0ea0320f61a647b842dee1bddc13ec5de423c1be6fc590c31e8069884a5f87c37d7e0a2a2ac6fb34188f91bcba00e2b87b65002e2ee25461c2e2ed35a09d7914fd0779d3bb46748a530ace5c5006e200301b9e26d3d7738668b0b1fe5602b7579b7b4a904117010957e55daaba9baed75af81537ddff4d20f16351786c1d +d8c02acc14cc767fa7b05c3a06207d5c861262b850ba868193d9f82b7aec7d9cb656175af823171ae4c0776319a067daf1c7ff913432f4d0133c2b75076e800d6de11debcaf71f6113679e4bc16ee76a3de6b191f6d3cad0f9d2ec82cf415c8412fb2213f0ef13a67d3898ae4ae1166d439c9cf4b9e20f2c2df83319e042c3e5 +e09ab5e7d7b2e37af36a0efa852cf2dd2d0c3356d28a81a8d860745806998293b9c337c88bdcc1c20b41d26f50ce1db86a67c5b08d5bc7caf5082b1f6b9732f8fd6e362d6fc9f3c7dea1babd701a97b41c901320e21cad45dfacfbffd70f2d7484c2df74903b13cceb7c16a3b694c1f3e598185fdcc2fc57e2c6e5a37eb84dbd +e5f48e4163389097f7f2557916abcd1f9312212df0707edef38698f90010aa7b700da25b6c8d3b514d6446b4e91db6f8c17eae2819104f969f30a07e9112ca1ec98ac4461dccaf667a48a552a51a5eb1acbd7a75f0538ff2eb6d8bd2c3b320fccec7a318731274edb1a09b6116eae22be0f3fdc914e462d2575cca09f0ae3365 +e402a052a7a9b2cfa8242c5d82973bae666edb84875b46fc25f708d2b102ec88ffc81e775dd01ff7f80f86974fc5c628e3857827466858b6a8cf5b1609beb4ac5a2c295ea1f07b678a4c5f4c9a9279b91cd314b6bba8ea68243beba2754d4be2159ccc1937d8a65d79934e78fb70c26ef9aeb114cec8aea0c82cb5ede771f8bd +c71fff2a5b3ff0e26dc3822532912b9853215321f7c64f7d9c185021164778ccd16d948dc71373d5ada2dee3e8dc0f9c4504d013d5222e2a04b3c566c31959ca85aadb18a843de651a1280f28c3b171495cd3748d24b21e1d5c05bfabf7a718c88a6af4d4eba69abb4eb558c15ec988708d0e10131e8c7d0d11ea6c64423eb3d +d7cbf7cc537909068a0722855a09cf12b51530e87916e6c89696ae56e23e6fae0788e2bf78c6547bd121e333c76ea86ab23d732b793a2c402799162c44ce27951c1ea985ffcffd7b0f94242b295bdbaf3b8b7082066757d7d9b8c38e4134fb6006fcd89a00e4ecb97da349e5f9f93950e973ce136e0c5b07c4bb1e79fbca0485 +d864ee108f8b62a1d71199d384358b2db77aa201c67689fb2c3034e3eb7fae2fab138756a59809d330e55bd15f41451b1d106a25db63d9df8ddbe26798c03062f0f7dd8e1f1ae43fbec8ac08f919f348090a6b74abed675d9f55028fd9ac991a32ef3b12678d3bf7f6e63705cfde4ca9f0fa864f693e635502ff578828bfb70d +df728818bc24b802d4928b3fed26c687bf8d4da2af081b0a5b7e8408d0e1e2de2afd236decc06e8b58d43e064765535741273691c905a083424bf82ab2ae83563a7c00d43814220569aa54615e7205551bb79fcf36af9ea8c30799bc37e9ecdecb90355a92e5d9d62328059eea240b67e36573b51d11c9df248190839afccfcd +d740d1962a65467ddaafb33dcec0247d6a0d3815d7a4b1f3da3e8ed0ca75e19dc02b16a71dba5fa28d09f38ac61352e0a870f8bfa094b459f5bea40cf42fbb17567211fb0af831b0c2112154762650da96d76b73b58c460f837ab8f8918a2a081f7a04716d85a87f4676404b03b467781ace02ec88ec890464c13688dee050ad +e1762495c9983ae9e73ed7458e667553ad221d6e6b675764f89331005ce0186c6d308d3ef1f911244bf4ce0d588505f7b5559bbee448d8373c51c8ea98ed1f3b3d112f4fed7d560db106c96c5fcb6687779ec1f6f472a6703a70cbfd2d31d607ed5e2149d19204ccae35988684b60c54292091c6510e23e36653d3925b14b525 +f311353a315073e78a275aaabf28914051637a5cb165eb300498365c72c6d1e67bd2510916b31ad0518c52e79e19915d9a361624d4aae90e852ae780c1d43edcea4c27304fbc9c120fff5566e361d9d696c99fd01a09580526292e5f626a8318a6af6f34665971dffba3f676d64b4a9e3cd8d6601de4f049c54e6a69f4fb0d35 +c610a2f93bb2952f6173ffc5cfbac1fcb866c4a61d2d7ce84932b63e5d1cd84ff22f00bc64bcc134e012d0e960c022c20fd406e8b1ed4c50f74a684e081a347e8dd8530f8e4c8bce1eac6532738d067e04d30b74f594ceeba4fdc49c3bc92e5c002b63798edc61b7cfc4a83c8d8e264c094f4d68b81d3be22db9d1d63049989d +dc83d0f2c3f7f9c7fe861259e876a071245fff737b963c686b45d421f094e61df3659c9de88d764072995971fbc688f03c5ba77170ed1786b9aa91b312cc008a9d46cbf48328dcf7a8a3ea5a172b88e16a6de0635770f3cbc47fae8904dec0f998fd814a7415e9f8601938cfd23f38aa9c0972c5712651834a23627676d6d98d +f8a26d32aa3c0a5a555fd3d63856e2dd04a1621e7caa100d3d775c67d864a6f7fca4f0564f5866cea4b6ae6597c9e81c7a67ebc8e7cfead05a511bbe1aa998630e763e4bae47d05c98b6242b32511260fa834b5912970b94ddd996bb712d361c2ed4117a6a7e53543b9b8911eacccfcb4d58d7d4b60d8f4b261b0a426125619d +da00566848c01f70b68f38c714ef36b49121604e951988e32e30b0649b15e5732918c5c7d830bc081a2b1bb3a16340e9fe8e6b4683734fff68c018e85f58f1ff30b54cb047e6abf634efcbdf080f6438e4817fdcc4c10f3003d8528502704c09e99b6a65ce88c100164e9931f4ba544c3deb5690357a0bf5f1cd9b5c6f5f9bed +fa5a96c584235b346dfa9355e3fef370e71edbc85826c3c202b460fe60c72a460c1d0aa5a4668ee910e8058c6ddc20e1f30f5b6a369cc5e2e262001388fecdfb030a01dfcc830f8095e808c439e32c1c22666b81f5c061ee279069c67efa9f905ecd04261da47539e10d1545d76f602acc4eed83275755523d8107dced594d8d +c9c78f76f133f80c60cb1ad3413b7c40afa5da7859ca268b899a75ed06f09d85dc62d054d50d9b2f060f1930bd150e6b0c7e71a2bf0fcf3d02c7425ed17a0b3673d3f4f9437c8375302c8c5f35d8409bccf4eec3438d7d0aab52c25be9706fd376d91cf1e2cd43ba19a07b76dabdeeb2650115499630fd7458aa2d42e128051d +f05036e195b7ff5750867782fe51d704d8717cb0c9ee23d598fa0d2d7db8f1105685495cb095a05a9557ca4dc8fd7948dcf362715637bfb171e5038217469bb646029155af6e83821d82d50a4c8064a2496778e8c073fca484d2d2367c52bf39cdd98f1f2bff5c2362f79ccf871a70db99a404d33b1fe6615d9dcf64b2b2286d +e6389326de9873443429aa1213f8f39322c4dec5f62d5b4fb938db5ef185adcdb29f5d4acaa7b784fbf9abadac995e43b5298c2a06f34c681e08e29d100f240676c8d798b141335afa8fa06e8e102edcd542318dfa190c981be80058855125b1e1bc4e860864a6b2daad46293d166e5ac6d33634e6157731aab64406aa198775 +e28708b6c2ef0e6eb7854970f88cf767a58ef73422bacbe3c74e208b22133ba36ba266c56ed44893fddc0ab3037933fd4d174d9de58fa00fc1a239cf44fd3f53775df9b04aff3c3daef9955480fb6b01374499d0b263952c3759f292455f720274fd892755a58d6cccfed87fe7dd9edc9c75a554cd1921b7eab0acd38836558d +cfe5a09a3363e7fcbb97280be6f5bcef49295b3a2b724d8f11e5eadc42e0f58370fcaee7ce6024972e66fa40afaa26c4762281dce1744664aceb4a80bd356a282d42dcb3e8f3ab25ff9c98d7a06e41db8b1ffa1ce4b878b18c9b06bfdb14a0170af5d2895a125314e2f36b8d3b75e5b6af12b1c7ae99e87ff942bf5723993ea5 +dba8a5680de66065714e55eec51efe354ea04fb3e796023739930227f513f003a03d8d0b70280da58867a8cbc25bec56be3ee98c251185d0182c656246380d6088ba4f37b6440eb8c1646d448e34909e17b4c51ec5696058b87ea9182b509a963e5b2f6b6c1ed0b70c99ad3635338b956951c47fedba1f39681e05cd7bd8d7b5 +cec8ffc8e7c03f70b83775d4a2d3eb6c2949fa9b9deef69c1a698d1ea5aa1e090e7a7a35ccc51b160a94a997409ebd82043b0a6ac7461556118b61305ba9006887d4c0b603ac1649e489380ffa7f4972e8fddaa959811aff55e70e34674a5281525b9ae0750aa69d531d73a8ef7e8aabfe373d66a752877a428fca260093cb3d +d90b40ff3961fdc0b9bd0890d9d6ce6f58f45720b6e46c97ebd876e248a054027c40fa9a1a6b123f1d119ffac30f60a836b558bae286b768926d82ba6bdc5c6c115e76975cd2e9f282e165e434229083fc57f2a025e8de756b01ce83f011e7ac82a0c4a995a6efe6878f2ec937b2b642cac433fadbe6bc05d4d94cf1621b9de5 +c51983be4bf08d37e6bbcfcaea856bb66581438a118537014b3812b01cd7b482b8192d03c21c3e15dc61dda8e729353ac22791ecf4d197ddc7d57b1063ff80e0c6dc6570a2088f670f2a401bad33baec2490941b68c72f2c99f3f9ffae478e3f253c4bc2a5d5df040155da0a484421a0aa061fcc12b5178ca4cbc5494383e0bd +eae065f0dd770e127b9747e3f5d89d33c7094ac37ba2ccbc63dfd7d4f2f208d6500ea8e38d6072e6716a4899dbcbccaf0b72b8812e34a699c6605ec008d8eb58a27ca1e1ab0500bce2dd236af669c53469d658cb7681355d172b65f496871b04d16b83c512858b70f4fbbf9557d51397278b13a922031160c1131b10c3c32b55 +d7543c8648c0a7230ec35252d0e9f4ab6d281cae438670a969728f53b5867fc7120110a1be83d4d4a7f95bae092b85bb37adb630db5524747db6bc3f350fda33ea8539e14b31425e3b099b241439efedc44f0c99a1975b6f545dafb4edaea8c395d00c9dd613a1cbf80d755df8a2d614ec5e5e83562d28a6e739b2bebe3c6c8d +ce98fe4c3e7791ddefcd1b9d35275bd2c1f98500ca0e533aa6fdd1752162852a212a60d1278677fc4b2bc2a32a7e67518c1e8f98fffd3e3bbdee1e4999b36f31cafb59ad586796fa40e5d5f96233dd3e8dd5380dbedba349d529d5ffc763f091fb1a1fdc5b012de244fe3517dee4bbb53a5e89717491a689caacee4a21ccf8a5 +e44142ef41cd39b3bec3bc40d7b8979cb700ee9ff6316feeba9c64ea173ea3af565bb7525929f247e13c5e8d7dee841be0f2752a20c1ccaa019dfc26feedd45fbc601cae0f2b6f170be95216ec176ad746df2b1cb3b49d8ceb9ffdb48de1aaa1ca1fc7cdd7cd6f1ad7392f3a1ed5536a82db646c4c029d10c2545d8655697a25 +d24c24ef31e65a1cbb3418e1a091398c92ad8fe1022a13e90d232aeec05e2021651a774d3bf5700139dfc523b4980e9f287d7f2dc5271db70dcf5e3ae6b12b15e057674a13e5c106975d0b98da8edc756c3a038c95d8bac78a0bd9d59b64a5d65ba3d2eba47a729570b9943a74f1d6838f97a461921854c45f0a55afce001865 +f53009a9c7023f570bb32b16c64df08b5e473ad7a4695479ff799aaadcfe15336c2c41d2d9b4436eab9c51a3f8b46f82f151d10d01e7c23f1d2413e166243a60c30aa686a9d79fd7a06694b56e62eab2e9a38334c95cba056a7e354c9efa052fc5abca6113608bea0654857f608366e3637a46ac63da1ac9bcec8575ba391f7d +effdf430fe6cf83e9ab57fa9af31038676bd7efb035fbd4929e305c88c2e86a9d7fc7d1984255b400a4e3ba69b9c039aea84c3bfc539954ea966b174c7e904968cc3594e62caa9d495b379c69f4be4dab289f9560bb82d86d093dc07c828adeeac564c3afc43a91799e74746b6034937f25a7ffd47a2e95f5efcf216fd6e30f5 +fd312c2d37a7f9bc5747c85cce2bb9b3f11faee8eb0cf9eabb5e2b985b6d79c0be0542b83f730f9b0a7d844c96641ca2c646ab162af73ece2b3dd2b5920746083e48e9bc2aeed08b73129d75aa20118a1ec0f4373403c5a82fc1be24a2d53ae8e127bff6fb842d9365746325e1ff6b825bca1b10bcc44fcb7753cd93b4e7da4d +e19bae43e71c102ec61906cfbe7a1c50ff4f517f9500a647a3d138517eaa32df011a944bcb30fb399844cb8b24c4af8e33d893e002efe6d9513e8279a08e2f0d6343387e181cd287459605999280c964b8e4d1eba55c5476dee6970c4405a9872451bdd013ed58cac1d619b88300e50f83922038a96dac937799bc86de1d8fdd +e45af63733bea0ce335617f63969fef91160902dd6ee6208183a5bb57d91d5ea2a1180b90c5b154f7aefcb4ad2b2229455bc2c4c6abf9bdefce1ab45d2692964779cb7461b85c2c81c6e09eab23eeb00a0aa6bff717d3dcdac23d7a1f8fb1dde321227538cb0a22439b81706dcde9aa697694e421d6ac4cec47f7d585eb1b5e5 +c02e43d1b9223510d290d7eb00a1e7836ae45a4930970651850804396627c634be76b272642b4f9eb9732f3f91635761b708cf52d797fabea83cd640f2e4cc85dcf358ad9f58573ce0a663e3a4dc4b35b3a9e4cba2af9eb34886bd67e09249cae43c1c99419fec69368e7be280d31df88022a062eca2915007d3eec666a19555 +d01d138ec72d3cc8be8a256213d130ddc88ac122f45ce1b8816a6bd828a4881daea455646f470dc5af804ca7e8bfe83944e59f3e625c1de06f86fe8867e50444ce019ed0bbf82a020139bd0bf8a4b0558182d5867c07b1081fd831326e7241908c9c83e459459721c5dfbcc85ab9a4bab4c729f30ccf9031ffc7204264c6468d +fd3915bebfdf090a857dba66cd39ad8c087cd94fbd3127cda816cff9764c6b402f3995f642d85bd820961960188619a4c1b3ba044bbd95ce38aa1c9c53a72d2da6cf8098b63e9e98f8f7293999cf7f061cd8d38b8062bba16dc9a8d1a499a02746478c5b670394e855fedb6e315ee1261fd8f18e40ff50d3821f6d9a5add7a2d +f5ac41e9861e7b80125fcc26557f0fa67cc1d1e2d1afff1bb0dd9e19287ff65b21a276021d0ab8958abe508879f38e91b46414c99fad0b6d301bef9dc68540cc0678adde95b7cbd238840ebfd274d4b0853323f19c625c2996bfc1740e88a5d098c7c9d4659321d5f6d04b5d4bc4eeec9e6aa598b4538cf876d5a475f90b142d +d58d247519881bc39adb7e9ccd1b8ab178c43b5858852d84b0f80f071559af43997a191d1f17ecd5ab37e78beb22d954dc469e7d6b457dffc05f0b908cc526c50e36c484bfdd037a8bd59afe13066cd2c93dbaeda276da3cc8a1404ecdeeef6624494decaca9bc2052ad9d5f1a699d739e2f5972e68002fdc38b850e77a56515 +c6877d5d0212ca82b394c8ab47464c59483bf1868ccb2cb1661545659a65eac46aee551b09f1e465b3169d2eb90ed643143e982d394e9dfdccab3a5917ea2b4e631a828aac0caa24bf3324b1de5484844f176975d93bc5a3b4d457dcd39d0aaa5d29ebb4207e03009ac30160faa29795e9f95338614bed64634c1572bb91ba2d +eb4a8bc143dd915e59c99a1469225be57b152e6fb804e948e7acfb6b36b10eabe0383aff8f9fccd65ea336b6c1427fe88bfb88d4b1265842375c8be6db4620eea2b45c9cbcad7db53470e1df13cbc19017951cfb693c4deaeb932450ade0b22fb5f8189ab090278ee1d28504a5483976d28955adbcc71fc18e6544433ff5c035 +d4a71ec4350f51d22b5546c6d7d6d07f1160b41866101ad847c412c39c84ff052d78cd5e2084c4e6e6f85889eb8e3084a6b0a60d9088b42ceeadb7a0bbb9366d5bbf89814c1b7a4045761d0b16778b0b1e9a8ba1b5a6d1139e52019978ff31ad93963f75ed98ba544ba7805437177876b37f2b7560314af5511c2cb43d8fabe5 +e5a5b5a02380762d273a3d808abf781b6409955e69ee510137bed632f18843deebd4d7f81f45913f57b7f1681cc9731eee76ba99f5fd0da8b2b2bacb15dd9ca9df53b5e758f0b8ce323ca7131d1cf675823ebceadf9f9a816eea392adb963557e28c29d966dc24c29147d59afb9db9561aa9cf200ea3a7ef284dbdb9c4b43d75 +e2399769327dd44829b3915999a66e29d023b82e52606001bf07cf1de15b2cb2685431a0167845fbcd06b8e7cfb6ba78dd8aed5edb44bc7c4935e5feb2ab44c1a35bf97dd24967b21b725a39260b32fede553f678c4cf07b0d4a1f23dcf34a75f49f0bc5b10ea517df13cc57aa11d89c00b23142d07ca274238c3dea132e0545 +d08343b82cda4e6743a5750db867698a28d55d3bf763b12b20b5096979be7a8d82dacb50c9cac513d3bf35adf608b1001723cadcec167ed6400014afea8aeac3f4f9e30e8ee46d740ff202c6236a8a85d75b618d291a081e5e145a07174bf2b3099f140cdd5c656670b5ad209b82a6d751a85a91da8c871ed3843647fa5962b5 +f19d08d244ae38b667a3eafc49ecc02c57ed3765a9b6f5e6df373dcaa34d184727e1e7e2d67f2463945ff05b4cdd28251e02fb979b08cf4110cdb4fa5349e74572bbbc661079a631e1fd4978942b7acc46888865b2fc5304d959f9c389eec03bca5a67b8eb9c85fdf381eccae9235e11aa4cb3bd670ef4d0a695a60c9f345bc5 +ea9733f219602bd2f8b57835c0260e5729c33d805e92768558b76ed0c434c1941ea514a0f636bbe6a62a954ff288d61a617958157231b0e51df8e585dac28cfb49260908c10a561c47cfeb6765a383f28e8a2640301e99ff6f22ad8b310938fe9bdfb1dbc1f977936d31ca524228e047b9771d73bf7f1274dd4c8d3c1d8d725d +ccdc84ffdee0c939b3428220f15ffc02333ba05373bf34461403d5087462ca6e33716806c61f68722dc19016bb168f10c0564a6838ba72e90db7a7e53561ef725a4b2d2fd46642b478c7431c0ef4f867ac42ad9adb88c4cb3c49556d4bcd48c553240099f27d91176bef4260e76b33ea684330384d997d8d863c199e5d2fa12d +fc8dbe56db6199481e0e7b536a7b11d1dfc6725f8c9904d20c26ad95f95c45558e2d4925215493052c3a1922d0746777fec9b10564a2a9352fe6367a089545f54cf1ac34204f683907c4c43faf300e42d21a07cbbd91dc6a2e7ec1182a4d43573b71b1a6e6889b24610e873fabaa71f25224eaeba4c431bcb20e196ec7ca2dfd +f8d0fbe2244f8917d1f3a0f276062d4f55386a924b2c43c027155a604e2b13d97c8c02cbf081b36a7014139626a553ba32b44aaab79b4b32206233256c8e7e4c8084bbff1e98e877a42d39b9ae2a27fbb89a374d1ed342864c4de01c15bf7832c1f1a7e367899e7cda988aaa46e8dd199de7bf596312febcb8ee78fb167cd6ad +f521cf6c8ee30acf897098cc12b22b02fb9413ba7b453b09ee30c1a9054ce49913b0be04caec5215668251b09db8beb273ef6cb98a7d832a8262c9fe0008652000dfa184f138b6087d79ddf3addb92a7b5af54f143eef7e3fa9e1e136add0c4259306dc3853b3cb9f55b341389609adc23ab0774ea48f0cd95ff9cd243e12b85 +e9f9e5446698aea25c754a3a109bf6a98d19b9d8b70254afa85c6c5bab62d1ab9db2a5901b8310fbdf00851bc1d57c6f5e5af582f4bfe3a67a961398f259a08f176c1062cac3b919cea6616b1f35319b844cf9a97a47eb166aa5f470b7a5bbeee6b051f69181f9c8d75ab71118f6459f1ba6c49b41f555f3c36ff562f8734fed +cf0da6581432e2b9bd38e4bb9d6497e3e09ddc23915531002cb1006271692ae28bbca7051ead4ebc16471028679b7454879400ba245cb4af1d7b4f5c41ba8278c6450a58f22dca5df7ebe945e67834012d064645dbfef5084f2567abb2a13944ea141e50fa4ed460295d90ef40d0bf5b0a1b2af8e8c4e9d52e34c2f707b2d675 +fc98b4b70d654a1aa86a64aa10a13db39bcb025a0c9dbf572dc1df22ebe96f155df7a1d624e85387e90cf6c763a32bd955dfa0ed99f37ad71aac4f8570d7a0ccf881b6cc4fcb91a62e1cd60488048294fe2dba071bca8689ca63e07771537c7e36deb5f0205a58d041fe6102e81918aeda2b9752b0d136efd49b71a98c7cdd7d +cbfc166895123f56dd9f5f4844b8a1f566082862f6a7cd0b425e1e90f92e129d64217e3f755923ce47572e2e8b1297aedcf3044c263feec5517caef9657698c3b75d6b257ac61dd60da87aca05da46a840c661963f423b5c76e5812741d54a1793f1e16f1d134d3196cfa670ee8d62a691214648cdef7d12db935da44787aa45 +d258d504c6f3d59ccd8dca3ce517279a027fe433d71e16f389852e341deba5eb2c94dcf8714687e7b6a6322ad390adf5e08942568c02a5e586d49011458f2c823d54a859a03e82410dd602ab3b5ad526e77f54b735065fdcdfe6c1657e31878e6d15689b23e1e079175ff683ac53a611a74032269477b5ea00e2a087cfcf2e4d +f611da44eccba932fc27d436d8ee762e3757744e1b2f0edaf8a7c63afe45675a19f695cb1fbb547ab2e3e5d00c804d8efaaea6f60ae35a5e338e5a648927bbf1fb7242898b376e0f66670ae2c0f16d75fe9279dc97015822725d617d09909d04bb4c48d097defeb5c9de928b0747715637dde13b23a37f97483bd87cee7a9f05 +f748f838957c169a4bcd35da0205727f4e036733a6ba5200cdf695c7a46124b6cb39b876354253d7394f9e3460ae9175e82da7771c9a0b2c812d442e66fc49f2c0ef5c4de0175bc32ecf2a072bdc852aac303923d40e0853e0774c7cc7d3eb6ac6bbc63bcefea3da62aee1d630acf23ca7eb4d0923451d19eb2638abb4dc26bd +eae5a4efe1e981d4ed08ae37b694f24b0e6c16c6991f3d88265accfc88803fd7a51498d9f6cfe2bfa5bd4948ef82ecb87da6b1221495cb117f0a5312284ff3678ed7d640ef2ed7b19e348e7a0bd694dc28196781d2475c45d6252ea2ccb443e1860df490867eb607127e2472c222d7bb36abf85aeaede667decae255dc43348d +e8a6152e7462c848d36f38e356c47d268b763542a5665465e4fc00c57a391bf5a735b808af29b9ba29144e93828a9f10df2aa2a198a767aab846614035963d7175d320e7aca496a8e57784857dcc10b571823526bbae7fa16102b1fe174ee3719b0e9f0b1578bfebbc7b77dd3658ade9d1bd6cad35bde306c01f9a43dd168425 +dce3db498d870b98be37fd5908c1a3f9b80372540bb627ab5f3860fdae340512b848d888d31943c45da506683ed373f9dfb078ad441c4a3445bc0b6c290ac4a53fdd53d758503684628ad1722d5d27d306cf22767c3ccb82d6be665622a6c1614e78e4079b3d537276b4ed16dcb2daf1ae2fd3b7301830ca7f18ee10d5578c65 +dc0262673ff106b22fd8f7b0e954504681bff6492f0d76c4813a8beff028377a21696e04a1875ba357e5a21ef720b22c6da618375d5dbb40677629e5d1f197ef880297cfc735eb7c16b1480e7fc437883118c2a17ff7a9adf24415c6fa80c2540756e73c3cb313a1b7fcb58f4ccdd2f481a528ef30c413594146d86e508c596d +c31f4efa0071274e62c6ad18672d29e8d0a34ddd87332c090b19c48140e531ae99fb16c0e66ef1e9258d417dec22be932eee3e8e2d2d1e32f83714f815903b348a52cc583c6376384b81520427f7ec1a93174885da96c8fe5b6f4d2023936fbd216b67f8e0314b6555c38d245acd5aeb83d7b05359f54171f356a9dab4b07715 +cfdcc840aaf8bdd98c4274ace9f46d8036df8ebbf027c22c22887f7804c93d6dc578659abd3d28a6a5f8ad889645c7e2b56057a3666467734183fa59e703fadd01cc2b08909f76a39d06eb3c06975e9b57f67c3517478af4a4457604962eb656920bb228633040bded473f06f055a46045ac54c2c63d109b515e360e5095613d +cd789dbf2f41a8cae05aadf109ead16729ca86da3a303d3b4ac05ccbf016a4f09e18226a6fbd0698c2f9d52fb37baa4b2427278fbe50d64c791a0ecdec22a1b97294f8a21807d82ec09ab91bd3fafc1a79b9e7da27cc7448813975a165ea18771367896046eb9924b358263c279fed1baf36be8bd82ce49de66a304a7807a505 +fb5fcf913fd6acb1fe6a6fa1cfe623631b3eacb0fb1af53b822a2ffb0bbee8cf544bea5ff17cfe897148470a928fa9290b35a487b8db43e2aedf67efe174b71409c8b15e769bff98888f2a69b3fe93d6e958cc0b185ea58ec5ebda005219446eb55d0736ad2ad32cf4cd580e60d25e26f1e792e637c3ac528fbdf1501cd3851d +d7216df66b03f51eaabd1e945db039ee72fbef1ea3f79846d46ab083ca02d74d7068054ac05d5ee5b90ba84c81f9cad3a969945f7d4ba547c8cdf42de47f95542f886d33f1a6ce7172db2fa72b5daac85462027c9d0aa1ed855b7dc1aad537935f30469beaccd3248dc1b8399f8cf627fa548b03a01c33e9d1238681574d937d +c28409f6abdb5ea38bc20f01eec110058cb90a07c1063f69ce8170cf8879ef8679b25965f2c985371fb7b40a2298e8cf61aefc062090ed32dd7477a99f775e39bbbeeb243b4c2b90d1c6bee88647e595e390e3a0a3d2a2890fc1e5fbc1299d63583170fd614ebaaefaf08e9ad323342c9acdf0dbfe2150f89eca4402499ca4f5 +f135258dfa7b82b185b48a111e343b46830ba562a63f53e1ef0a0cedce0d8b6e3e9323c3cceecd577d859f5659e6365085036ca7f15e75fb2fdb5f8d0819c8454f948309b2571237dfa5d08275182d55786efa8a274c5ac6641563bbf115ecf4f8cdf24b5bde89b90490c72a67fd5ff2f61d92015d4d53b5af3c48aee33838dd +dd23c15c71c7be2ed8d55fc98cb7b00269a3ca2f93ce801013fc77b7aab1917bfab2133dea01e0581ffc8481218eb7097f5ceb0167c1f223c387088f2c2d108b06d2bd1ff68e4255f4cf5508a067fa895fa27d9739bf7be72e661fa69163638a04766d8f9d07fabdcf010cf02f421ba893c7ced966627b5c6739bd2e70613fdd +f542781d273191506f5b5db33aae73a25facdde2967d84f1ea53e0fa98d43fbbec42401cbe771f71e1d1a0d8f48680739fbefc1f701546e856cb7bdd57c65f96aa4d686b9af695aac3b6ae92742d8ade5f6f4574aa60773b6c01f533dccc720d9ba285c04013a627fc0a7fb26f0ea48482e94d0f89437ad9a531cba372233145 +ee4e65895d9283d8717a958c088cf3bdb836ed38f4c6eaa9b9051739a1de986781e90ffd268674aceab08e95b2d0d7505619b9fad815876972f3391ce66b8645370c4050cbb8084f97c4eb7ee7dd85d5eeb8cc4eeb6917984a8bcf36f2539fbad5618b6a80e1409e48cdbab7bfef14d628d1028169fb6787b98a38920a558115 +f34ea6ca038a7aeed8f446b56b1ea9a175e082f8a03e0b764bef95a9e255a27454d4018f697c91f76a588e31dae7a9f9eb18925aeb19ddfcfb0b5cf6cfe253c643f3bf541015b3a0fede9629638c49c81650b8ee9cbe1026e04886a689e0033980a3c364069dc03dba3154da56807b325ddd96412960c64e915a5fba57e657f5 +faea3f46d8d6236c5257177d6f27bd2ff7a2312d54512c5cdedaa96effe4810c216e39075136577c91b2e0022f32ab111acb05f8a9b051c9d11fba8fb708b1e8b8154d8f3d6566a52efbfc0d8414b1162b435bd6b409382e1b34fb3d92615b887be1ad050578978012aaa5192a8cc4612d29bda58989bc50b837592ec327318d +c8094fb8e642491e29d3cfb5f0b214255838b38635f637dc8fff89ecfceed440300a2cd3553633d927d88145109973923a89b427cfa4634f77372938355217dbe7c19ef20121b4e213ec86a790ba4e867dd45fe83fa0a51cfb28fcbef983ff0c3c4a3e8dacbd3eb5a8e2b46a571e000435e7d871e8f932d4b56a808ed9a4dabd +c4f4ebe55a4f83579e37ba2779811b10775250d36bb5876ca8cfa896c53c8ff65be9689fd68a8a39281d053e740bebea27fd781f0b3ab5be3f40308d6998cc5a95f1d5cc095e7896825c6e0504139cc5f2438ae85a048daf28a1698538bcab8231a8bf449b1e1815b442be1eb1abd9019d0058b18e118256be7a70293e133b3d +f712ecdb5544ce9d3c146f317d4850dfe9bfa1b45a9d4d19dc9ab459c592274c282edcb33ad398aeb22e6e41b72670a0a4b0373c73c829570a0acb8caf1c7034d46e849a6be96db32e2f99bf0e0382920b6503a8bdc7acaa801c69ac6f0192b9c8293c7bb79f3c5ca82bb3452b3a314419e0b53f72867048710a7e02f4aea76d +fdabbf57b9d9a703eb7f9d698055cac6e6a541a1878222839a7813b84d7cfb75a25eca26df09d2cd42099ebc2269e7ddc60612f5e3fbcfb152036ed3cb83c56a552aff9ebb00a356705f3a4ce9100a805b9ea0527065b48ad0f6655f342fecc35aae1a715a3e00fd02bf177d352923117599d3ff30828a0c57fa650116df7075 +dce3548054466fabb408c58cab550ebfd604967bc785844da99e08a5e03fcc84a973288fcc3cfdcadf7e3d7f0a13d1146189713658c1c32a43eba7a84e7742c1c988acd1aea84acd4ba0dc7d87e3711933289c2effcdde2570684cf3adff3b54f15350ed40af0a1bf0aec47d77148e1937c9762abdf9c7820bb2626d4a6ba985 +f086ad1a65ac4b2afd897d1bb7895ec8ab5477b96d4fe6b06128515843c5584f5b8d3f4b5ae3deecd0719d3a772df47b37a8d938710edc57d5bfce58b7e415b4c57f623f5e50d456736667180b0a08cf0372f696d65f013cdd7a1a2e4dcbdeeb0bb1584ac7383da048cd518ecd9a3b5e7c896311abe96793041de812366fd6cd +c95ea65ce5be0a626740d2fbbd4df61913a5eb682419831b9709912d2d2176ae51f8d23b685eaa15eaa4fe76859ad148f6a2407b1d4461bda13a8ed337e9646259be2000010b2ccabc5b81151f7c59766898659d80144f36c4f4d2dddfb3b72d9c96b1e59e6767b64e046bd6ea612fe45434b68cc7b71bfe3b1936d2873aae2d +e50160abeb3931d7740cb48a3aa0681453c31eb3983a7cabf94cb581ed81ea7b1cca9c2157d562e63cd30e572e25f56aeb3102ebbf7e9e86e1c70da9d7119e7917536b375527fc6ecb2266c1264df2823355c8a7f3201ee8bfff6a1886b5bbd4b05dc78a7425d6236800732d0b7875b59417f0ef62641fb1a48f9b2f4ea92dfd +e4d5215833bed28784a0ad5dd2869b97ae32d0f6ca5f4333e5df45a4135ae61576a83161d03229ad935812fbee75d4f8b5e9e9444a25332855af2265c9107c24a048caee053ddd72b0d3adf16ee669f8f8cf1ae84a65fb947f0843ccf76ac641ff1ac98464cd36d80b243c2ec15cb8a6fad3e45435e503d4144892ebf74774ad +efe9f954c6f3a607b54fd893c9ca2fda5df4614d830053248900f58fd3ecdcc1ad994c55b1739b476ac8bb6d19aac6cfcf987f2fee4d0187461318e6a10fdf3b5936013bd11c582c49f2ad1d09d1ee9460183f45a22aa42c02bc940be4170fbf8e205c87e8c64943b840562ec7db4ae337b1f0f977fde638d8dcea9dbd9f5cb5 +cc4937af80e67e580d30ee54f7948481213053a49c27dc0dfdbdbc5afe79b50f103492daad1cad29667f5b45f3983311f4a3d769fa7e3493e5fd8f9584a3942191104198de7a77e978671a2af406ba6accf1e8ff883166e29ddb00823cd1d4d6689d287bf7d0d511735609668557beafec9d6546bdc3fb631c474eec3e2f26c5 +f935bebb45a3b09d044ee922c36f6a0066e8668b4717c5f21cbc18a36d311caef071995cebb139b39c5077ff3bd5a527f858c545349bf3f50dc0323bd71835e1685a913f98d314c85ec1312ed0ba310187148ae6988497e508e00c0ef1bc72023c91ec8ed528ddf1ec8edce3ead3e88a05a51bb7ebdc1fac29cf596cbaa49c55 +fc26c66972bc7b013f0b879557e341a1ab9b05fba4a5580e9607358674359856e13a1439756614bd6600202cd18f932f737e839fda6427945750345f7070a1e317d391816d58e1500d96188087174df8970cbf8c7c4359da09a143084871079cfe68f5b6470e9eb6b8508ee4b8baa271fd1993203b0f71d074c3bea1b31cd1dd +cee883ffeb32eae7594cfbc23d3cbd5b37c72da6dd7d3d5bfb286f7dbe460ac3b6043f78cadf14715b656dfa92d421958c8acfb43194078759c058565ca181b32c327b94a9086011b5952ebedc80d0e8ad8e66f84ea9d9677e19c2424e122f3c8d987072322f24c5de5ca61b5abc7f0aeffa26972a7a2d241defbaf7af8ede45 +d01046b4fe46abf9b099573273cf61303301689d00de860f94acaa64838d76f25365bed14039eb287e24ddc34a07c183f6a2a81392fba7d6e1d4e0602932ae13339de5a788900a96d58fa25042c7568fbf8939ab65a5e47320b03ddb72091895056d659677ad22ba1ce6088ad515247327ceb49fc5e223d3e828050c5ee8a155 +d1f9a4c8b9d2d6c6ae0d928fd5c2c6fbc78d056c6804223788fbf1f9990298a9fb0ac57d85dfe1d1590c617212d717b292e2dff15279b973f03eca220b76c5cb1b699b49221e91a88b0619384df979f21ef63a5b72ed20c533388ba23d96b6d852490c5837955aed263f56eb862bdb50cbda07c65417b25864bedb6cc6cc39cd +c477431e31e33ad6357203152d48df7537ee7d4343dde4580bfce608d0b07725edbf7e16d5a6ad8ddd79ebff06905225322e7ecf86cf2e9d6cc141caeccdbe4c24babad2da9eb6f696620f056a42579cb5218c1acaccce5a1b3a76dc4110acd74829a31d373825e31cfec03a58102044845d8997b9ed93bd1e5ea96e081d1015 +c29d8fc580e7ce4685181a7c43c82620a6eadff437952b73b655b0683283561f067583447debd62a16b7e55b8dd6d4d2f61a99165006d04576025129c027f2af7dd2d88d7f1faec453d96bb34ad50c4a1726406f2cd50cd45c6cb670cc97d6a0809b556cee10c08759b9b36344aa8627ffb9c67b159664678ebe6b131e124f75 +d64fc2f28b0bbbe44bd528770722849281433f156ca40cc2722d4bc18df19e48181cc7bb7265a68407c8048e95f0aa88706bba6d9b7bc9e78d54b4ac028a96b99813e514dfc032f436ee7d284ca3d4403ba94ca5a93707a20fbc72d0897d3fffbce43e252a7d3e53ab66993cb2e1fa02120c4897dbe444441a63e2f7bcde3a2d +ce6dc18edb75b0a352738d0292c22d924c813c1a9abddc00cdf4592879b566e30d9e98277f96410b2db488a96262e32fc1d104e776db8a10a931f98524fc7fda19b3867910614835fca01a02241ad34dd02719ff37e980df15c16ad99b1321ca7c375eee6569894fa9a07e9f4d7b0b49de1586d2b2243b2c50981d8d1e76ffc5 +c7a9dca1332f1c903d260c67444f62c9cf1d8b53e283199bb0c2eb84a72dc800557709e0d77cbb5ba76b01176406814073b633bd56af3bfc89b8d499480cef7e7355dc78cc58a8a9f11f8221ca79cbf32a25c75f393cf8dce9d45218b1280595f2f496539b6ba9e3972c08c7b9d0732fe9488754a6f4555cabc331dc634dc0b5 +d652d68072085772edc617f0114a69dfec0cf4bd7f7cd50160d9d8852e3672e013522075e2a0fea5f6c0418cb61941ef1ac6bfe3021d68f710a723fff5f423509f75a4b8094dc4f753c791120148ae4d0ae44bb09d09529cc6d29388a5e90cb5df5a3c23ca6f559c72255f8f1db04eb00fa36143a95b8e43bd71172d9363387d +d34134232eb029ceed44cce495cccd5bb84406f5dc027b2901cb3b57f201a619828bb4dd7331f393430a9e1a2c0ba039c4cd8895d5c1c554ec9b48ec5c1ba98d29fb53cbcea1a479afa55f1fc5f00c1d086441af41a833bef4758b7c65c9dd8c2b34cc1fc63c8d558f72d9736c858cf6e182fd4140036e9b590958f580787abd +d95d11a752f12c2d04e41d0bd2813dbea2272e49cd943c72993e38a88f32448105e1cb3816daae65d7486f69b6f7a6f28eef4a5cd5e4ad28b47246895f5b79ad4aa4a73b0328cbdd1999876ed8908d5192ba68bc0a446919081b64bb91b299c021cf2f9609503fa802d86545a831e39a8c4cc775362f73a3c6d1214ebf7c7bfd +e59903fd4b578592a5d6d706264846e17127732a16af4104235850e06e78f22d900d8d427d30b4d6c74dd4d1f90e0abf1ff0f17cc8cfcc9dbf910f90a0518364634fca337aab25faffabec1a7af9f4154e10434acdb0b5d1ee705c198d0f2bca3ae5b32b15b91883e87ece116d6b0bb1afa564d3846715a8b3eb0521ee3bea5d +e90a1f94595c3a7bd75b90b5b6cb021e32090affb36bc094470886dad266cca4c057e48480d92be364d02961b7c88992dd3010fa94f8189be92241beb96bc3a2b0b97e3b0a88060b0e2f17bf0458b64ba357f89a33c6e5c0f0b0905f9eaa1ea5e5d492e4c54c5c4fcbdcc41d546809acdc26e5bb46b53ed95e548ae261db0f15 +c0bf25c067104f867cc0f8e86553c2d46c9dec62a16c5472fc88261d0c557109575afd749dc3cf060b31fe5c25255db5c5b428b46d23c5972e0e3c1897b97876ce743da8ad0ea9ad00a10d0f6b211ef125cf861b17b9ca21bcfced9aef4392c9728cee93b61a02a6725b3fe92804742231a2589a93bb115299cbe571e8188485 +fce11de71e18c85d152046211cf5d57be81b26abf687d094816d5b1bc16e7f446f7f4bd6164db6c7d0f60ad9ee7fcef172517188f1221cff8231936541baad418aa310896ccb0e76986ac6975bf6b5884234e6bf8c719874f6ff1d7b98665396bea1a58d4e413768285d8d1db16dd496b051f3f9e8015ec280eefb911480cb85 +d71ea7196f642b90f8ea627a8f941655f6472d7fc02f4ec24c55cc79f95d661183121e7324628325bd52f33e2f1bc1a14310d7f49930462feee1ce1dcb787af70374a29a7152eca3bfef0138e11e85394335ef7f8b9ac51a0314fdc795791c9ca0b5958c381148b12af682ea6ff5f731d6b3b83cd0cdad9ca4f9d4829575d94d +d7fdca776293f33e09c416d2c1ba70f00f7b47dc1ca6a2c8ac6ccfc9f1fd1e88344f75316a99be099789591600ae779a4c78d4c12f4a0e97388fbd6ca63f437fe1def8f31671ec27f6f9bceec8405932c15da2fe3ffe66c6dc3bd0aeac146867790adc61bfab3da2a0d358594746debd018d2b7d58dbca16f4851269bc806cb5 +ce72cddb8418186abd586c8fa62dfaf121e804090937c323ddfeb139dfed9e570b26e2e28e69ca08ba5515556959b451092c83fa5648fa769122987313415e14bc664402854134518f131f58db527d163db3cd13062a9af658357801535ed5bdf24f97ff18cc824ec9af6dad9a2d3921faf7d84218d1f513ad262f64dd86cadd +d5066137aa3101b001a99b1ee411dc57a6c5ba33dee3279e85d2c62510306a69c924835e21e6541d5c2fa3f74ea4e908024bd299c5f8e6049720e1cacb935f8adab9b4a3e78f83555ea835574122c2cfc9b1c2d14d0e4e56e021e06614d5e76628982cec22995458e6482f7ced45f757716620d27a53935386ecec12b9bc73d5 +dd62d314161fb6c7fbd6942123a8e321835e19c5b3bd6f067dd713106c83a04903508862541e1687d6147954334f2315595e41d307cc17c47a85fb0016fd987c2b6273aef981780aabdb54e6f8eaf269f97af56b8190fa2ae67af1a3a60eb924f0e00e9f0e5345ee4ffa94d10a1058f5b364234e6838e2832c787b673be173cd +e2b1d31e084c148363d4a41c685f15ca460e1ccabfd25dc20b9c51844c17c281fe72c76d2b6d4a093108d5cc88f0d196d24baf65c90af95a905afa7794d9ba873c1fd79fda78b878ee970c8a7a3f434ca44cd35965415b35ebff7c635a5ac74a4500738c86f52db8a7f7c82c4544766bc726f4f2b2a4c02419430bba3cdaaecd +c227213c7f588e4bbcfd2dbf3ac650c6610f03e4c4313ddaf02791a75ae396a25c62089e11e47326e585ba8c5c8e6aa20ac1dc690f32d600c162ea086f5eccff3029d1bc2f590194b7980379680edcdc6f21505ee678057c36245c400277140541d12346f067bc77354fa2abe8dcc26a2df51f0e9b5d05f604e179529d2d226d +c90dde4f6f6f00220fbe1efa9accd0d33f47c2c7f25844d4a3d58964d1a01eb63cf695b4415864b11d25c69cc231cbe4c1b8e8c47bb49715fce7769b865db47c8242882c528765534521de678c800469937a2857ace52f3bfc74aeecdae1b82588c7a3ce44b656bc274ee80c0926985ef828e5d7083486b3df38359285cb8dfd +c3e5c636529c8c0c7a842c434708663d186b95f8cc1a69eb7d39c7e008cd1e192defd05ce9fac89e93e57e64b99ca4801e83e7fffb7f0d5a46505d4d5522ca84f00e05b2e895706ee703b63b897775f5950c8bc5d7e2557d617b55eba35ec36743a198b4cf239d95b9efe62f4c40a8b3930eeb82d07c186d1c3935d3a2229515 +c8b525c6c1d8ae599b7f7841cb55d4ea2af528a77ee21d840b45d644104eff3cf467ea7bf0f0e0bbdc5a81cc4606907712d1235fe3f33551ebd11f6dd54ec3a42d3b6569224d0579bf587cfdba19a2fdd8bc8e30229e0d11cd7536aac5dec9475fee801900f6462114c0b148bfb210c7a27f9b027f1886abe00674fce8ff761d +f59a9242b778b65b309b619dfd19a877bb25a168bf0c323c54b03e3635eb31d5345030dfa96130b157c10b8c8d78f4733c0610f4130e99279840966b0115b31066f6eab749fb930fb844b50265d36d04873a3ab0197893cc62b6703d61e397c8aa3660dd3cadff9e020621b8b90b441ac368f773f94d2d2d4d35afb9ec12a14d +c9d9ec80523510681280ca314ff905ea6256ca3ac6225e478705a662319ec8365c36282f1db47774d85f00cfb3d66aa68cb60a9af761924829e992f0e5058488bfae552fa0c8d847bb4546dd71502d63db7a2b713122455d47912ac37b89d071b272b99af36df64f66f803d3ef980784b0da7ecfa117f75ef52430896f15c3b5 +e979ad6a662fd41f6dbb5ee0d3a8f7a928ae0f0940dc3982ea5a1168a46f5910ccf0d5606193eafda19ae97c5aff2b903b0e3a89eb3c879ce0e13cdf43a2a177c8104d7fc121bb9406a826900da82ad4352f4899d04af3f57a225c86c20a175a96f941c2c5eab721db904330d6bceb8d6a7a913461e389158708c9b7b83d8ecd +ce2c29c73a1a121454c12d84784165325ab05dca980a0390a3cf0af78409cce3e67ab9df103543babc0e35149a0b8b9c677f9c71d37a59eb27811eeca31ff7d568430a434a1c03720541cb69a21947e378d14711f17efcab348fee297e53f169fd5ab195b4be24bcc8c68a9bc00b273aa10a01dad64117cb7615b5fd88d0df75 +c3ec5ee6e08a212829db60b82d68c90e4dce2c6c419dfd7402a1a4ead2c4d7d864d45e72a2b4f41a09a569e4863b2c78c60d071188d927f608f1b2c623aa23b63d8ecc23e253b3c995c85416dc4ee57ff0a63e2e8884f191feb8f16bbb578b5054182b3edd779a0163a873685b927b7d375495571fafb20f420f8ab95c0d0555 +f389ef5bdad020e5dd82a2e0f9dcd3b40fe30af45ac437a727047a934137920df2cde3dd6097bec3a2cf142955651661fbe04cabc3a19ce2d882d9e17a8c18046f598216e3b975f297819bbeab264676e4ca1acd202eed2eb7bea7812238b33988ad4c980dfb1eebc643b5a7b9312969f4adf746844e9d714b2180e6fb19a69d +cb8caf76e9203122c7f3cfccc7d2924ec29cd53ddc0709ee0902237d445c2cec1ca337b1e1ab7b6cb63cc7f5f11e50ae8ceeae9dfe11299c39390db51e8a4186e69a74d0775bdb38d1c2c5f8024ad1810e298285393293d3118edaac82a5d8914c5dff163610db4bc4c09486eaad877840c3ddd16c9098f107aa7614499ecb95 +ca106a4be4fb9b3c203254f44debc87417b64ab4c774f972f12cd1b3adb1c5c0c760e68cb145fbd02c7b682f451ce467f17a0f07b5394e7db5fe209d972e3fd2cb92b583b6446740fdf38e292d18b4818e824f645f86a20eabe722c0f693984b58be5e29a56a40ff2589ef5713b5ab2d7ac803b72936011dd436cd1db6e2d6ad +c69e4a726bdf444c038ae2f146b35ac11f03127abd71686cdf8da7219ec3cc89fcd1eb4a6c83bc6eca90373c8b998be6a05858e52a370b184b3d1a2f4a280f847eb5c252c351f52151e13a83dd7aaa2eceea9361071b13037cb9197d8f7c4055ce4955df497258815f59f2a436392a4c6f97166882189926575682fa328ac98d +f6a6bf9a76484194e7e94c0624ce91045be44e04c8c25bde647d421e6266694a4fcb384699cb98cab4d5e3498edba6c581e868258af1b628557561fb9c5e5e23cfc9effdf4f46a788587a1422a4817152b28d67c7888c9543673c2d8eb3a5a51ee01ff2021d7e9f9eaace73873bcd189f84704f2bd9ad5c38cae6e188a3e4ca5 +d4aeb7fa7499ce369691bf04ffeb312ee235060d0a7d96e2bf6398985cf0b55bed0b8b34a53346adb47826e71b7ba2490af72f9d92a33054e1ad8e203233e356f5de9874525de52e74960948dc6a2dc8c9d1671b463a167ac5c889d5cdc6fb6a087b9949f3a3a4c15e1828979e9bd566f502bf9d12e4735dd1b51ab9ef7dc97d +e1324d35af63b7c5475c19d4642a776c82b69d3dad74278afd80ae38969d6e010f0f78c7a17dbbc505afdb00f05c0371a8b100acbaf7b69b4cbd46cde9cb11ca43d36ecc1d109aac95a7d6abd11f088787d9d8ada4412fdc06c030339a10e1459939bced6b5b872dfbb08e33f0c427fb94e0245613f0b697f483674af9f46395 +e4e6640df3213f25799c6aa0c723c17cb67d707261f3ef74f95bdee8d2acc59af18233286136a9d86610421205424d27f21aaf838b7ee361176c0c89fea4e1b79ee48ea438944746d527b1adacdea3dfefe2dfc5de313876f211cd3f7e3543a5cfa7f07624e913f65c506af956011b854549b6b956c951a803eeaaf6f08e9bc5 +c3c8a60114d2f5d38e14c79b803d2d7af36e285daa5654da567e6feaabaf74d6165304d53bc465c0c72b3f9f7961a996e77e066f37eab45808ef5fc1bbb87cb252307b88eda73baa461b3ac1cc44c37af966ec17755fa66040bd340f2a77a8158c247638008673fd3cf4f98ed552ebdd52b61932b540db5ba90b939f2dd9a585 +e18fab58b61a8b6b28e6626cb74cbf9b1753e51ee3a8093b9283cefe7dd576f2043192fb59a472bb89454b2712ff6bbfd390dff0ae2ecddbdefb80aabe82500c6e4d35fb99b79c6f17adaaae7ef87443189916566d755e8f2f9726bc7f3b1d8253a98877bb5e20d2e8bffff9445cd8cc56af3425ae0901f98494678adfe82e45 +dee8564ce74a01b800b97ef020ae40870571f9d4a4488f9e11bd5ee1acb37310843f065d3b50a5e695104bd7f7fa7b5ece9c5a930c81bdea0c7a140e7e107b6a31597dac446b1a10a8030c9f2de9eb5552b796635e92ec9d98dbd311bb4d18e641d294fdb9dbe3816657cf9980b9fe4bcdd0c1015bcc2053dd1b267ee26b40e5 +e67803f44dfe83b81f73a9b99ef69b758f15a3d108f7eee2ab55e9222ddb611e65de2862bf867fafbf04af4e33e80c922296baf1039d4f76afe2537f988d17e16013cd22dc33e6f9ac8ba04f6f166c44666d572e2515db1de362dd2d45662f5c87b148faa1bef73aeb27fd75123faa6c0ba4aa27dac96c8c08207deec65d32b5 +cf02e0be2c3370c707986317d450090c72ae8e1d3b2f6601a0b2fd62eb7531bf9b883fca519362541d176388699f2ea0434920f11c08d418701bfd0fcac8cd6b23b123551d37d53333d361c5135761f4edf669939f5e9c932525314e623356c155570a6d253f78d6dc0ba1865d94383239921a3b2bedfde0181581dc5b822a7d +df15be4ca79a4659366701c3d33bb1b31a337733b1c5bf32944f501316101d9aa23b0c5426e90b9ce7abb5a489d24900e4004512e51ac7af4aef6a3a6845cc1d82bc4c905d1afede8a0d20f7f38bbd83e9d63eae6dd7d8d69c480661d802890fffc1dddc682fe03ed0241c130e8b2d00a6f8f5f2c99b27c852d6b652a2e8039d +c8c4b2c92bf417257ca6a493b1dfb3acf2d57e49f97a873ae34727d2977d4fc339d36017b08cfdfa4a6a544088ee3034d96eb9c050857eb914a2aebb5acfdf6632361e9604a52559a831db5013fca0eb9381b6c40e421064e45c534f7a0028a3333066491e7e1b35cf6aa82389e47306c7773b745221141744d723c85ea2cc75 +e2acbe5b77c2da5bf137081388a217e53e6212e847903fc2263f6c099a7ffabe54e8c200be0f8c35685088f32d6f4e7067d36913854c064773b4fd6dfd0aa7b56eae581a5c2ad01f25b155bbc88845c005fdcadda96dfc95b821e15889899d2c6a9c35bf5da5ad1c886dd62c25753853fb6c1453f558f40171c33d73ae410975 +f1e94067ccb4c0d8465a57da3e31f3d0a77070bb82f7253a2cc410b8b53b12df6fce41c457e3cf25a86fead441f3019b0220f9b62740dae8a20620843536b0643ded83f214ac93216c93e747b6a74762798038236778fb0e8fb2dfdc90002995a129ed27eaf8fbbee89bd0ddb60f56d30a5778078d4d61dd36ce12afec488bfd +e3e06839335402cc2a140f9b3da84df94187bfe716eb31e4523ae2cafeefffebf62af5e16a379c3184afba15da90895581eca9c4f87f4d671d72c384121a7999200c986b33cf89692d70d171eab1ae7bec2773f243339ece696183d76f6f7b4038e5bd5bb801f7c4c9feb25f3a492f5073efb161564193abe2be7f59f2e1950d +e6eead8428cce555091e3adf44d15d2e312fd5692cd4078930f4820d2cf47c5a040164967b629b0ba1b2d06e16935671f608e1b0d972d070b9006c0a8eb248094b9afbf778c89cfb1f80606ac5413e2e6597065eb0bb0869ee40fca0cabe995b4f6626e6b89eaaea90f5f48004233e845e291386f3d298b46dd5260f618f0f4d +f1985216060ba19e8e0b77afb6f04ec35a7c7cee04f9df6a306b4da8d76ca5c92cbcc7a728bb22ad5b24e6d1eb1f7305fb8a7b41b747747503d0198c38df69bad6c6aab06d55adc79537c6d8e606620b545864e3394dc5c0d1916346cc01988649d186c48dcd1937d21834eb194ed3ef03f2d114770632f4d37a14516cca2bed +f9c9f2bd2342e3c4dbc5894122166fa39625cf16ffcbc84a71ae8145fd6a66e1dcedeb7e6f264209f0c877393f21862d81d2c759546f0fdf8c41708d5362a4f8b6111a3a7f732af1d187ae1ad693117b0d5dabb08f64f9c256153b160d4a957433a7bd780e9956d7e175f15ecc79c03d3fb0698238426c07337202a32771ec4d +cb2d386ba2cde8f38438f2774b54f75a9be753407727da7eddb882beaa0fcb6225d1095a980ef842d06a3847fe772d745b2e615a9720f608fea86281a9e041c38628b4335ae93b446f19a495878d350f9664e3d4b80b153e67a7d1aaa73728477889de9cbb6de0bb7a9537d7327c49c5a99bea50c96c9d53eeeb576010979d0d +e1045e327e0b645b22b8703682d618317e0b96aaf79a8378e6e670c56c6c0075941a48d4301dbf66968588f76b064fcf34a323846b09ec18be65c744d4b3b86583991b8facf99a247fc84078c53a2a0889b573c247b354ddc50be0ed49291762334bb34f5cda0bcea7ce61087bbd967df9c2790f901e9c135847bdf766e3c0d5 +d17d7c04e0e73f0af70e8a681fe57336d20b1132167808e6799fcad00617671dfe513c63c38a1ac28b390a16649574cbe7090d09aea1e9cbb4542ee30532098c4e0f5243491def547f771a6da3d741aec52e6e346d8018ba95d2ed500f0ce37a723d3f99bd8d1f0abdb72af353569817a815f95054ed2bb94a30b96e2e83cc05 +f521ce6d6aa5622862e18019c1b08b71d313a12bbe15f27f6d68cb14e31dd1eae4f1b5b5c85655e685e1885edf7548bab4f9284804cca5a874ba1750a79765e6d74e6024239431045519a5a5a6f9326c5d2bf59711e52785d17cab0ac6c2bc8858fe335e2bd6e0a54a39fce1668c382a3d8f79a48d5bb0ce7bb448f0f46d265d +d27b0a46e492d31872b6d2670921afb3c11964a113bc425a2116008cda9bdee4f2e1f008a96942089755c1a90a80f62c18b3ddec2f22a38971b63f3d9e23af975a8c51357699f7b11598ea7b877e6f0901215d2e8df364ef1ab0106eb0706df83285bf3015f12ca98688c8d919aba4d630516b1211f8d6d8f71cd99d0c599cc5 +ef72eecba638aa1f75b33a9d91981f780b7f5e39371e020c8e468cf72069891f8bddce8eb86075dd459de98a0cd65af719afaee5553fc68b00f8dbf87e33a620bb767d8740b69f45406bc8c3992525c94b3feff1a7d3cd91be83d24d767ef4836d01c62c74ff946ab61c5e5d0964d63c5c42ea56411364d7fc4a4b3dfbc8e495 +dae2195ea4ffc79e7a0b70fbae8d74cf51cfaefa30d15c0e9a054276037a4504ad5efdb692ff97f0c456c3fc66f21f71563aed455a1555fed1d8f7fdfb14a126fd475e582e187e1a8875e25f7959111afe8f141b0bcf641367f672d024a286766d902d7b48de1e40f4943a07adc20866cf2034d32881ff1756ef2a7470886c45 +c393aa8773a783ff411304ad3000ab42d9dcf488f3c4d6098f49db82b339ac6942288861268dbc76afd12c5f9adf3f61ac685d5ddcd80c8a3b639fa59e6a11c425cb4f90b01070ecf9810e5468e8fb2131c807d72dc96528fe3379995c383c36efe88d7f1bf4706fc64f775c4fa9dbaa738ccad52004540d134b51f912436d35 +fe6c3ab23ca3b1624a56147831d8ce58edc77ae99d6db6f17f889bb19f8b87ec488ecc4d4370a26978a553b5769f5803bf3b14893ef6f779dcd4a2a0a6821ad61e63a4c8a41a58ad3c1c5c62e72f524cb63992cf6100b8e7e8a1f9666d932f4f29724a3645cd20727a615161a08af2689749bcc601f37912971778b7d738c62d +f87d31fbc3fe86c9f4e6f2d6e66044b0b3cb461ec9b00c52747b9b7cbd1bef105ab9cfca392e807db5ff40103aad29641f1d0408eb4df587c8c44ff78729db10fcd76f56a475b3f16bd28a7497a939ae2afb8ac23a1e89ac29836dd5bfef509f23796a4038c899bc0ae2428cc3fc34564f4a6841ae920a50f838000039751d8d +dcdeec99b18f7d837ff301714ac199acb2d8c3e73065562d6635f6644a72693bb098d56865fbcb921eaa8c417719c634b7606cc0628e740f051677c920fe386d546aacf0de236bacc0fe221275566ad92250387c10cffd555d554fedf9ad3f7c4b6cda017a7e0b8040505483cc64285305438da2d50442295e4d535a8f9be7e5 +e786b2c5dc7d1439be99339d198b15b98cfc3f718adcc65bef4fbb86be6dc7bae3dd12734960659f4ae9ad6a45c66e0eaa6efac0edf6c0ba72910e1910e9056031b3f6c58538c0b24d5c325d7c1d50a78479f7c7f3e9cef501171ccf45f455e71e91b6f49f4362d0fbf8d8855da8574d888fe26398160323a45668f8ae62e9e5 +d960b0d7131cc252542f29a686a2e1b9b61bc5ed2da6208a6a13b461b4cd6606505b4d5e640dea6e11afcfc5caaee218e78d2026a5b44bdbf3c8a77f789ea841f52dcf2fb86b0078bc643341856b1d2fe18441247e58d03065f96d10e85620a24adfaab437b5ce2044f900239d868abfd09ea56434986a2a3da0e34fa1f59f85 +e9f06ff9af989968099c7585ee539702a91b9966cc1c0f6fb7c7a20f32f37b12697f6afbf0b27e16187893bd40cc24f53aa4265c2195a0f08ddc17f755c4e3c76a79d1153e6a2d99bb9ced184b4f031e7dffff14ccea6b87a30dba589ea8f65970af537297e40c17a94a4aa4504f03efbdaf05b38e6015a1102235897b4bfcdd +d76a70ac8966f4c7f4c87b96879541d573b2806996fb6a8a2054d8b56fa5a19e318631afa4e83b18aeeba714eb1670d95dee8760b9ed0f5ff17b8bb75540b5011405ae8a2da96d87cfab2626983de17a890e424a25b41401b990127d0cc6b1bd786cb2786fbe8080eb18e98558894c3fe383c7bcfe897bf98dfe95521fc12e7d +f7bd785aafaf4f2bdafbf38235f1e4c730e9ab5dc4fa3cdc9b9ca90b06dd9bf8f382ed58c7b0e34cd51c2cfe7b59345aa10839f3345cdab897ab7f553673e0bbf69ef0577ffa2b758fd2a6decb7a24d9818227aade82801f62c453b95e3087d8992b435e50e01f83a4833967a8b75ce37a760fbb6cae3e99bf89130e1736755d +cf26ba352f678c227c25e5147ea8de4bfc4310d388530d9bd3d0dbe0e9254fea8483ae00f5f0ec81dec0e42f5d1bf948b8519ce593737e318925de8c00c0214247abfcdbbc77df57d750b3a9c160b39ad9260297f7fc67ea2043d190bf0765a4fab4c7e6edfc3f08a26311de00e47b879b338097574e4a377e2387ee9c525085 +c6064c4add843be7a9bcf2582ced8aeb459ba930241002cf0325da5a2d2e1b5921479e50b688b069fb82929469ffedfa5a1180f7a9a6168168a64ef917c909a7f4ede94357203f1113d0c6d2376a5e39d37482511a67ffb65832a4daaed93f86ee9739b42c62368eeec1434d6c42a1fe53c5068bbd3ff89549029410740cc23d +ed15402f355404533c4592b42d93de22ac89ea83acdd01bc6b742ce77761a4743fdf9a069965a7d19e86218f8976580be43e4a1d978e0722668b060f95c0365fd9c84f732ea445436040c8ded47a88ed05172d17b46e92d26ad56afc99d0ae216003413458b2718cc194e559c4f141e593996bd9888d57781b5aa33ff1b44e95 +e83a24b27cc273db2414f5adc3d70f5b9926dedf39b4118298c908a26fdc0817341485b2c847ee98ad34afd0a316d32c03c455474f73261bd3231e08c09de84c051d1efdcfac30ebe0da967755db47b13928966f6d0cf348e24f6831a30942c3b971e74fd33a1c6a0997a4db9eb486aff9da54af901149106b991566d025ed3d +c76da67e64ab8b60d859753dd47d501e96d45772eb72cfe226dfd6a52d026034f4ac2cd8f4113ca8cb31b830eec8037f94e62273653608152de1fb580f247e919aa25dd58540902ecb868f5e25ab6deac6caa4dcd48dc9f35cf1939f1f22369f98e50463fbe9e368dff83cf27847e2ae45433c747e848d995fd26d68c9fa541d +fcc228f8f74fcc29e4d70f6e437d258e34a9db8d1af38d951eca478a66e56a776423b54d636b7537f46e6b1ed1d8e19eb03c865dcdd1090db77c1da5a695569f4f0b85d554ab61c8f65d04627da559d43f5b44962d38bf3ee742b9bcfa2db3e9120223b31617a631b80b1bec2cd7d1837e452d6307c4c1c7340193075fb2b8f5 +e076473f86fbe36192153f0864ea831bf5d4dd8cde7ed5d7ac0dcedc4cd36e10edabaf12ac16e9978c12c60506de560c18e3cc85ef2f5563bcd434f7c16413470f9dadc62f92b5b01328bafd9d7a2e5e11db723a8002eabc1d116593ff975a3076c679e3b56734873d51ef99fff20a2f9bf4f06665e5e84852f7ccd830004785 +cf9e7ba49264fc3070173fce670ff6ff6f11935237a557b68fadce974bfdec70b65822bf865394873da79de16f4e506d244477ec4ccdd1851e2cd2713a0075835fa59acbbee79d2439e4d1656328f339be18605976317882fba6b83dd21fee67c38217132eb115801ef009558886804327c446ba577dc93a92ad71b2888b825d +e8ac898dec76b876eaca1dd3d5b73ecc8a0c06e04c15608b1cf9cd20917d3d72135dcb29e03c59dffce2c2e77d345c8232c32ed8f5ee58d08ce2396d4866b3b09611f9d7e71a3eccdf46e17d84c53edc861575242f6301802fd237359ee6961bc32ae74fe34cf64bc0513cf9635d4f046d229550674dea3dfb7e7dd7a5a4441d +dead27581a5bdfc0ae2111f2bbd3a2c6c0bb996dffa395b4b52b9c30cded05e6a363d314ee9ff024651dffa44aa3ff0beaeb736b1688d9d40fe3e0fef53d4ba6c78446306d6ab6d014af2381df992a526ed354aba7f3fc20e1edbca83012e40566e121801018ee1ef32ee9687ae896b9aa2f3ba935f199c5eeb7953a5eed518d +ff751130a3aa372c26cad01df7083187cf5f6b1604a98f63687846634c3a6676515b839e49454eb344eb894dd4d9b7ac4de7bd8b8de3aaa103b45124e2477e17c0a44bb32f4afeb2522391fce1ba6f89f5596ab338a8cfb1b64848d517b96b5daa4c164ca5275ad8adbef3fba0f0115303162690de9f75aeaef3cb2a831c98cd +dc93f8f672332db4d675cf638d5c3a9b9ab7e28c011802aa30ad61846ee175916a5a9daa13ce7db426209cb409fec83f26f9f4a653a1bfa1c3e4de7318bfd51c182177bcce23e120c601d67f21b948060fb521f1a9cf4a5ff5a260af17dfceca586674084a012c3156e3c59b346707d6511b7f4cb668fad7e517e247750b98e5 +c82bf0ea27c2be5b5b90850621a508016f821cec4da9dabc473fbcbf0cff53e3c13fa3ceea1c851f638ca622d30dcee8519b30e54bfe7f2021dfe08c56a03323453436007a1a0d5058661d0e83ae6e746e27a2db8bc0390eb94a45fb9b3b6ff21f0874805b748eece85a21675b1bf0f87393eb64fb480e776f209dcdc288218d +cb01ab004a455102d265024066c28efbf293b3b0b8c5b97a2adafa84c2f0ee25c567d46dcdc4efae7039917277646f2baaf507ff8bed41e88aedadec96a4cad46b77af2c7ad24bad0cee415ef7fe59c5459fce5334537265db060fa1fef9526d21d4dc4a932c3d27f018b988c51fcc54b3d45757aa1e782e43f46e6630ab7525 +c8fb98ad46a049845c83dccb2c7e31b8b16ea956b9b7f30422ff2f53da87733b60c801751ab394d86449a8270f0df4fd25193d886b8ec7c2f2a4649f2fc39640e8634155ecc8a1a191f2688c1f5adb42843c9d7c73f7379082ba202d30b8ef70a397a35d26e9b5e49d4e3cd87dd6b051a642efcbef58b9b5cd05f349fa724ea5 +e154fd4f5be7bfbeced17aa18baba53f19837f0c7964be61154aa49c6521c9f38d7619877850275b9573cea6e4114fbafd3db7ccf9bd2ee023821042a5e6d8b242f9f62a7bb601d1118573a628bdf8500cec45235d7fec639b5795af057c863f1838fa15eb25ede388c5f7ef53eb9143aac8aca8d19efa3dca4bda97feec5e1d +cdeb910095d2e9345ccc30254efc1fa238ce11958ed30d24617110b02c18136b832293835d0963910d43d8247b9a7b19c49fb479b1717f4ac7b55a2888144aa4fa7360f9847fdacafc98097e7f0b3468eaf0ae8966fb279f1def69640794a221123168a021f85d8d79ea5b1702c4123369d598a4801eaa973dee2741d915e6ad +f8438935ba59e7c95287e5c2ef5d2950e736f74e6fd622f034c28beb3184cd9c0f62cae993bd4c1fcce3ddd5dd0b8eefe9fde9165211685907b55f96833ec32b3398a4377786ffc5b3b1222345b488662802bf89ed7a5b55edc639b9f941292336c51874ca037d33cbe951cfdbbe876f5fc995075cc4ba44e3f6cbdfcc59deed +f37918b706b8ceba15db3e18cde5d888270e3e01c5d5d10b5606f74047587671ed3c5dd0cabaacc3091a82786dc9c17956eaa129196d8b007b4f1540c520fa8c75990c7b63603a56a3200a1ce9379fb536cc2216c87d850085145e230c959f1ded675adcd029fd57e32c762de466b9921470b357ad945d12871bd9a3f25ebcd5 +c5d4d9b311fcc1f9d2d2dbfedc09c347d5d793746335a7f8db899cb6cea019cc66bb50afda64b84c2cf10ea5b72669c598924b1c9735c7ba423bf07c06158372f514e687f5284979231805874905cba2bce044615ebafeb93ceb672b6527c20f48b2917b1593c1788506b75df278881fc77a7c0606093bf65c15156daa594d95 +e63759f9d2559b33c4620d6c598532593b957d232b873ea35125cf190a1fb78f3a959a100d4892ce47b87c84748e1a5b232cdeb3e404fd6cbf19069f2c8de134458854ed4e07d95131af6c441305ec7a70a96058a2882af2a342a626430725a2adb448b7bde4f4adc0bb275e33b44a97d2e9329194f1c815ff57428a1e2cfdbd +fb6dd7d761b3a07b56cee7abf128faabe4ffe20dea8169b2cf74d3dbffb159d3e085cafa59b779433e89eca22895833c491d2409b1403a4d6d437c405848627065dfb0a67ebda9458e474abc9aad869ffef2399abba08185eba0f7ed58822224a981e28b0e7314770357de626418235987b194e8fd6dcfdd03194be656fd60cd +c204ef8a6c39a3f23133957bce1fae1158b587cbbd73797bbbd6e37aa86d747d0c8793ca59b658e9095602aa882f34cdb9a9d290ceaafd9d2116a15f6cceec75b0a150cd215d2e9b993c5ed17fc829be4126afcc9d85851e5d366d18b47fe90edb38e72262dbcac4bb701128c8a2d942b0f110c41d352578c323c1cd7f8ca99d +efdaab310cd92e5a7dd0dd4f5d387921fe5e18b9358d1f8d4178e7522f2aa1936f9bdd5de36ed955530c65f059aff8d177da54b57281266f188309a037533d346788175022f8a4995692294dc2a09b7ae1e79394b8cd9c69033ef8d4d07506fd0dc14967649456b8afbcf480bbbf1c6bb7d2bb0809c88c0f8934fe89b572d9ad +e3f62e0b73cb17ec33426c5a4ba8f4292e03e677f5d1617d938e93e54304f7819a3921ce0df73423902947ea2b4dd162517380dd48ce63f30e8b7df9d7194e75564e72b6809056d6db1bfa62b3dca60f7a017291f8742477efc7eae8c9e7627843726fa4a9fe78dddba02d9814844c6e8c54febd3e2158971fd4779f725f68ed +c3c9197fd49de1a9aaf1ba03302a0849278a6bb8460afaf38952d542cf7afe6f8c1fc40b7240ded7a7ffcb5b23e4a5b1507ff7400db4d19fe433524474e21f9673c88c098f9d033c191809e20617dfd5f92cbcba5c8dcfd6652551945d1eda48f6dcddd16ffc05dbe4e3cdb163de9eac0726b7dd8ca388adbe54858471319325 +dc87423787fb3776d3a38c010062304d7fe6f8e4bc5fe8e66201d9bfd724b601c5184ac3267ddc8cddf3880542fb91ac077cfd2b7a07b49b90a550f8445c1c68c084a77321c0d03d005c0e666a9ef3709c1708e8d5f5f2d82f0ec81a2de2fec456b22ddc5243b2ab19f64a74bba5fa6c2a091258c5916c2c49d2ea7f0a5d084d +d0012d2f905082a4516b64dbadf6a52659fb6065fa31f6678c00941eaff3d1e2423a57d9450fb53dbc956536eb00844326cbba017727d3703cb3d83d7e30510a25a0e3a030e4083c747a9a33cd8d8ad28d2b249ead1286cf1de4015c6022248801fcac6320d2b3aa398b7c4ece75a6a9d9fc19d460c657b9d9aad6bf7501a5d5 +cfa3a9a0b42aee7cbf76b882f2ef49bbb53f2eca837a6660714545c6a5988a819a82b3ff72f96c828f385b34fad06e52fbfc3dcc6e43ee9dafbefbff3f5111fbaf795e0675047a21a64c717b725d027b1df53e680d49e2a0fa68975b8d616790535e6da217b58ee3135043b13f96d9d9f14ceba25c80e698a8b6e79247aefa45 +deccd1e4355492e13408d4a9ef52ede6f736c3bb92c85bf76f264a053308a228a547fcc55b2b18c52615030aa71bc0118f259e8638656f0f912352d44ea4964ee652ad4a277d02a96cc6128655cd3caa276eb2622de7a6dac84bda2300ba6ed68d5883db8f45d88feaf67fd7af568c09dad637d46cca9dd7164913bc21dead4d +f05f8e610335c370350f81e7d3b8681bda7c0e51293550553b028ae6937115061873b575b342c8e0eb16e4a94a7263d405fee689dab1e304651abbf9dcaad9cdc3e0b78a78d8d08ac7bb3bdd54bce8609b4a741d10540e88402f74fd20a931b098f83e08efbf73ea2cd91adf599a06e3181f369cae318a388bad70258959e5fd +f40bd808d8983b526dd32870db7481b0026292b56b3fb937f2ca04a20063470f46f6903dc5c323dde933fc6df412d04d326dd3f2c3c63cabf2796b3a414d953f2e164fb4d7120cfb555ab5499f097ece48afe978a71c8a43deaecd680f181087b380da2186afe81e60470daba27cdda8f72c1e2013743ebb8c7c7836ba0d9a8d +e0a5aa6ff2ed1f0a13e9f226b1d3e1daa1dff2a82fbc24c57f4364ffb58fa6dfc3c146aa2a0c86fbddcfa6255398f4d5309e5116b1e05e044ad396c780312b36c56065218bad573ad88fe687502ff51a6490c10b3afc0db2faed8d282fd91f6245ef83361aee9485da9d7cfc4ef91c9d98d6ae5cf383d8513621290f3dc4d42d +ddecac7bf804349baad7591ee4130b79bc255a87ce3b3af695c7ead8676ddf607832ea50bf24952f57c1e19ace029361d94e6891aed1dc095d784e4147422676e52967436cc963af0914f335a7282cd7b73188996c01113d78ff465b609608faf2d1356ec58044f8b9261cd09cb3b8449805ff34abdd257479dfb7e699b9d485 +ed3e5e09d1a52ce643f484d223b312b47511c0b5fda60bf8081b69a6470f94713661b098f744fd144c1807d7bcb30117813d4d6f506d232c216cd0cf81edb59180ba2bf74ddec8f7fc1bc720059253b36ddb4758fd39986a097cd636c80acd11529b24e9dec6d803e87cf990cd6add1c6d5f16cffd74896811d05d324bff511d +f70b3ad2f71f7561b3afb043fd85a7f703416a0571aaeba91b098d198af0d19675245b53c0b9839b8a3fd4ef37b95d2361809cf72f0d057654ce018c9e9c9222419e636ad7b7b28ab9d0deeecc369869be70a511c15fd40e8e9c35858e04db42e6d08614d2e98754d85206ecce8121305400c3a7eb1be090406449bb100efbb5 +c3cf52f73bb03e184af1ee941c56e4e3e4280b78e2d7b3e9beef82f896fa241d58b5a260b8289708c88ffad26a3e907da16bdea925de7c61de15b0330f717b05693423ed0979130ddc3771d424839262f4135e270b396a899e40ca2f799a7ffee07e65ed428b4a5069987e010754b3455456c28183c46ec789095938d17be055 +c7e0b0844d2d1a7a638dd86b30ad2bd20caad56264c4ebd10566d876097c09785110d4238146ee0a1a219c9247a61b4e39fd342546946af09b9820bcebef102efd8be1b51902acaaa5509869b9ebc5510aa656261313b7ec6facc4eacadef66e758d976ebd613a1b42f0ee54a1fce38fd0096887427f61e007f9386f576b9dcd +d4149cbd1f05bec65413f244f06bcd0ee3405e734d57cd023569e58f8da93fda5dd2cd38c2ad1ce0ba131e9fe0d5c3e898699493276431ace3adeef0d8d74c0197144540adca344003f77a92dbd168e0320adfde66701df5c71bf439413a61693ff137447fde0cdba216e33c78b73e1c6ed6fc813b541041728688edf87dfe95 +dedd0cbbba3cf035e2aaf743b0328e04709b0a27089553039a37c46fc62664f4c3d68115e470517aa546cf3126a2771812ce0c0c2631f435f25966ca88e37eb49faeb9d345618de4403aaf0f7af33c5044e806f423b0eb9180f6ec797dd4374a08d3ef625377787203c5267c8f9014d32b575d124047da743681ad677303334d +fc1208a5ba359665264d35fc6bdc4b23a187ab3fd587a2cab5a3911b708c68dddd57cb150ae32cb3262393e24df810c38329a679bb452ab0eb7a70f7e679285f75b83dcf470390537e02cc0c83cdc6b45c0773589b43b144797ddb6336a8103365d09dbb1b5edc2e5d568079234cf7bec794e952b8f29944ad66e049d2c632f5 +dddfbe3908d0c1ab4ba1c000a2a154671f440d059da2d700a6eb8a46f43c8dd870f352b74e7c96aa4d12e7c7ad5793d3adfbaf242d1b48b32f7f51743f6222ad8f7b7dc663b7e43dbc4a07ad3be5694744e9971d156afaf090053fc24a26df63a664728c0c844b95fd2b46afb22f4d8c6e97b63bb0974bffc3bd146ebddd1fd5 +e0efae147c20338a15d2fb5a5196b402cb9536cdefadde4cc9427f5308a7693768461575c1bceab20e9e28af8f5ba5fd2c981065650f4adf4de6a460c29c395130007d623ca2409a9badd4e3bc00a1188fe3a19005eae44cd36c201126ce72e229b277b220959b76ca71005bb246bab998937818c238e8dd778b0058c28a7af5 +eeda184c6f8397794c654db95158c29a0957b5d273d1d44432e2d212e358592226a00b284670c7182cd64899398bb9f19e4b987ba7ab08fa09d8fb41504bfaca985f1da13792f5b44066c36d0036aa4d48b35ebb6ea6cc173928ab9cfeaf22a37b540b39f7cadbd66e91fccfeb084d2009e3eb3e57885cfd00ffc0ffcc8b2695 +d85227d4f2889dd7f1e39c15060490dd7bc2ccd84f4f22179c74f9240670b68a3a0a2ca2bcaf3ab7512597db68d794f20313ab1966704897b32fd993cc8a656467c66dfb00d50991c01ca979cc35ab7aa0ca463b31829a852f51ece4076fb8fab7d395445897004d3f4d6fe07cb4f9fa7d6bfda3bef6c1d0c4169339da897575 +fa6393cb5800304597bcf745fca14d20d93de2c1f99f3909511dd8b9ba76072e55aca206b562721095499a302f2c77f7ed31dfd4b5011156ffa6e9f96b45bfa1aa698a863d342561b2aace1414171e8280d01e902eea9b2c476465628168592550ba5204609a5b7026d86e85b660739beb085c29f7d9114df91bbd25d59a5175 +e2b832d391a032e7fad9bfd592bd8dd27676e2d64a7f237b75c3d33e6a58adb73cc536681969d88e768ea287064d87de15f93dfafbe1cf0fbf80403793b739ce6aba95b73312b419e31613c2cdbafa65f34393b14ca52ef3ad565e5ab28e4b12bc38199250162992cd29ee558f2fc41f448ffdff6d34e3e259a413b22b7dc405 +f9b8c2242b699145f93f38e0d537eea01e147321aa2780c0017dcf4db6d2b6157964c62c5ee1f16630e3c0c5dfbd2d79fc68153875f2d5231f64537876d7a2d353cd70802c227655d7afd42dd94ccd79dd123f86de8a524c96daacf0365d4bfcb3b255e4598fc119938b151fc7ebd4b6fe6188298ab65853acaedc18f1f580d5 +ceaf59a8150e25e680974300c03087e734c24de34a838035f6af22283da5bcd9c8c76f20a049d26c85efe92928ed12d2c8533d139a867b380697afde7376c8f78593e5b264b224777d525d4d0a62b39d4fee7c4c57d1b133bf181f7c5b3805b727ba0630cf28d48d50e55a05c6735bdd9e90e4b98767aacd8cca543d92239cdd +ff090e80f5837f43f9f393a2cbbb87657185cd70b0b7c7ad681480aa48e8f5d69773316c3d6a9d9af1c8a3ce9aed950484a5a77849076650d573de967a3e9eeff5f70c3230014e39b1b8ac200b8618c201d83893185c07e75befc0ab6791cec4f0523382b1047bd40296642135d9498715f516693c624c0ddfe0bc67506a59fd +ee12ade07eb483a078532f5940b71a9c71b2310d2d49b56df3b7d2394f75d1495be2ccac175a52b9228440dcdfae49759e38b5af2de3563230cb19c06acd0570fa3635548770ded37e0b0f42293e978d1ee0b26b8c105c78e3ae12de17f389eee748aa8acf91814043342df26391c9d9e90dd117198e65ecf9c1d1f5216dc9b5 +f33b2b58ee5e248e076301e4d4b77ab9c9d702924f95f13b486e272da16fc9f57fba60091c79a83169fc8f08082875e12acfde59d10c8ce9944bbe8e8876b31645e074d501c146c651fba3ace691ebc0eb18c57fe7abb0b1efa3b5a497ee7899ef95aadd867f9a988cc28d9d01a163ee0dce6782ae0a45409b6a104da6805865 +c15736b1ca11e133c090d5a065b53cd82e2979f44cb93bba041735f4fd339955f1e9f2a753f7100c8aa7d0df40b908a74a4419999c0f4736021aa171c3bdb5974aea4ba1db3ede0b9ec3ee0eee5789dc24a6ae4bda8c5559b148648b55e3a6e2412970d9c2b0fe767fad196b130fc88ef383f5511000af8b3f74c2cacf165b1d +f16569ecf0eaba1f622c8caf1632b24735afd2684f3a7ac86d8ec679c6b7fe9212ef216d37c210d3ca5849c167ce063d006551d85e2d40fcc12265a14467d8d36a67a9972b7b72ff814f90bdb473f0c8618a22023e80e66d6e0df8e466ea995fef20d4127fc3d690e803e4ff62ac8f88f7b384a7a219fa8b116269152c2f8d25 +e70c3cb7b95c703d9f9e4e5b9dd6260f3a4cd3deecb2b7632652a013158fbf0f5e4b76287410cb20b627737fbf7fa92f85081a13a00a3fc59daca503576d8b449b600f6d9c57dbb7c674309bb1c4af7fcddd90085b68713ec20c766c442a0ef136731101bcc6b1b9633ca344a590ec7b1ca611c6b39c161a4b8b3016ee7c615d +e94d5b4afc86cef446b4a4b0004e08f5b9b94923f907fb015e4959406d03a8acc13a51d825b3930d5166ae0054622aff440eb6f2550d51e7ddcc88dff5dc3a8f8120cf6c4a2f3e01902bd8d86c28df484e5b776d31d149a47a5cc842220a608eb0ffa175eee3eb3280ef12c5b2a05025537abe234717f6e2aa849e675fd4aab5 +f8d4915ed06d22f36675aa84359e1a877b369a6e556371b59690ced0f4d592860a78c49c6bdc8e7ea1a1bd1109dd8878d53bec463b3ea10801181ddd6257daf65aec29f188a706f0039003f436a2086922c7c1de0f251d6749855b0348df64308e0a0ca1fd0b7723dd4f35956662fe0aafd3d420ab19c5487756eedf86cf84ad +f35dc4c3be8a22c7466e1d8e9b44adf3e91601eede366fb9658446491715ea34524d76d8660ddf95f6c512b34d52c3cc4e6bed657cb6e40347d9cc46dc5404cc2e54dd8a370041ff1651e20a8084e45b7b73334ae12c19b5885fc8c626e9937dda3c673365f1c3fd785738c20c5723eb16e604f2a94c4ef966f577262c9e5575 +f265c490a6cd394199083e842612145ae5576ab26719701f92d9e084075d66f4f8eac3a6375abfdfe3197a79d45d30e1a6b05b2f09c5d884d495b1deeaaf3b5fae36541290093078308f0e003b9b271de921051bd13216bc16c996c1d73b3563a4a1e4c71bfb1ec962b10efddbf17c69b77621390a9922d63952cdd4b203a2b5 +f5727c0c1826e112487441c855f1225f8096dd90d13f152a49a737445d03c78115f963f88446f2c7a3335a371ad886150694cc476a0ae0ffc5adcc6368190813938f0744baf6e4def9a211afbcb3cd176166f3ffb23a48a793aaffa08384979d4482435d3126a5ede1665beae8426e0d0c12ad3c0077dbabca8d55ee87b8c5c5 +d793b9f288bd065b38d4e80160a7680af407bea4c05b90f40eaa8736a6a9bf41b2206f663b24205115c953f68cf2be1a2bc7073e17d8ebbf6897c0caa9480192c014f15a9ccf024caa11ef56fc35ca06870d8b86c41baa2fdf6ca00475dc3091d50fa452021e66db6cd58e8002c37b7b43975f23373ec4840ddf8c5afe3882bd +ef2744764125c14bd0109d542b600ff2c445c3496a21409b7ecb9dc0aee0667b564ed41d819537fdbdcd4781121e20c151cdb342facfb9ceb1fa39542b953d5db58ccd7bd5ad36e0252dede437fbe819312c6ebb9745bb0ffdd84f99b34ef0d323b89f12abcbc2e90649ca09372e226ee7009d2600109967ca0b55315062aa9d +cf3cba2e0eec4502ab476834d2ed47764c44d45c750ac23115f49c52ae41ca82f36930c92e424b8daedccbe1cd905068e43ff1dae15093217de2e42eaee6f113ede1e967677bf41b8de614329b9853d7725da58134bcbe055a73827bae503b15f7e1487e453b9252c34006e20127fbfbfe2a4c3d74ce558bfc1734e4728edb7d +c9f921d0852f020ba370b4f2d58dac49176eda353b7db9dcecfd73c1465d8c7a1f4dbede864d6fe320d8e5a2386cbda7ee51d9a0efa099b99b1128cc0ce959a1938fbb85ac4c0306068ccbaea4bac0f7ffb2adecf215237e23e7397b949bfa852c38ef97d40071780b379ef1747ef0be6ac7951f1499ae383c43b86cd34658dd +e49e960ab120ed0d6f3c980febfb5cedc0076a4f3ae7f3b5e2cf9f9ca783a390fd77b674d6c73a9ded0fc3f6dbb1bc91242780ba1f4edcd8098f207aec2ff3bacc6694b6bcb94efef3df81a99c4db1d89a7d3981671d0f2f62a4b1900c0bca3aa690171d04a927183d381e6c67fcd7147660dd43a554aeeeb737f3a5cbf1d635 +f2f9ec42a76b676a5951bf735c3398d8bfde2ef02cf24200b6270745316de9fd949c489fe43f1b4b6212903931e29bfaaf77fc0ec9b0dfc7177dc23fcca35f2a0cdaf82d8fe53c792854322f98c538b968efd86d805ba173e23dac68c2cd0e56796959a5ce5bcd195f89a45ab5e371b0d76b92b348c5e461fab00570740a2355 +fb2cc865e608517979f6f4ee62be241fa5a43f326ceac1cd90e6389bf8046a03bf5bece2b7d3772dc0babcbfeed93c86e5f712350bf429410509a680e4ae335a0893463c423e84cd4ec649bccb376d84b67699f84c8a7471ee4ebf7b5341495be4aade3f16181e21ea1624aa8fa48f266e3f358c5527e89cc2973d9d02b08d85 +eb853c389114d97737af83290fbfa382ac883d68dc89c47e38b5b252a23a61a29a5709aa98333c9f0868f72a3ea5999f4d7a853dd8f3ed18e1acbc0215c97ea23e2154343338d3451d4c5f656eec491f9c2f2c02d69d760be048ab96937bc9a6bd60709066bada1dd197c0c028d87367e0c02fc4a8f19468734a96f3a94eac0d +c70e66e78b8c832a330525acf00fb556c3fb9902e879952ba4f5ef4238248b61d9bd5a15f9346dc23b3cf6b961ffcffd853fc2ae240d50b53b4bcfd7f9c6cfcebbf84714dec1d15d3904b8eb506a8a7f5d5d9313d195ed2655474e1e54d1ae6311721475de884b5118accd509d9f734ffb051f9eed141c22a16a68c96a9fb24d +e9ea13afcfa9ec4b657cade8c373d20c2c13b4e76ac74d00aab43922bce4fd990127ef8e6d65fd099cc55cfc42bd19b9ade8fa71eab087b3231da53ea39ff01b2e8114a74f108757abdc22cb06fcb60a159dfd15ff52d1234f8bde2f8849a78ae24a1091793c69b1ae9807e065c70692cf7278ce739787daef86864762f7bc1d +c886f6a02b642d27c8606a4d933e9ffc1af53449324d5da647a427dfe244ae2b2b2cfadaab181298b07dc90c1fe6a900f1aa078edd86fcfb3b9ca8a6ac2d18248c25afaa1ca9bb3d391b15d277a2733f88df7eaad52d50449f085a1f0ea81948a38a7798193a52619428ad1cec3c7426d922f0dd8dd38234a82346d59e7a4c75 +f648344d2a961d9585105006b9db58df1a1c0bc7bcf2a7d46a5147a92a333ce3de0e8d2faf815738dedff3d6773ffa6134635601f9f4e491a184577b224f377c8580eeb35cbf8ecd1f069d825af966fd84cff6f2332e0fcf3c3f605d3b6fb6cae295c2f55c10d46328f8f8bd29d6489bce95ae1455771b0cc1c807bd74c1bd15 +c79a37d4b999e7348b78d0fa08b7a7dd53ac0b4beaf0c3ac6b001cbef235b42385075e0c81afb247df1d0b733894caa9dab15083c2fecf9d93706d1e060c143a5e1d2c865ea9f55acf25998ac3965dfa5b1ac476a9a6d559866c7e6b31cf78289a276bfae51a0479f899d25b9e08631f17719a5505f418a381def0a772b12c7d +d88b9c146f4e0199fb750c6666498bc1166178fc39169ebb5326f517181830778015833a4d98de263316f84c6af44fe81c6d12369e9f77ffc56f9d5e64f612bdb96e7440f84bc7f473a5f31684a1b32ab72595b58dbedac75f6d1808977ce2428f8a2ea87e3a50aa20748b0fdb93af66ee8489b00de02a62eeb1283154c8040d +e615ba364ffafd0b9d68d3a9de8600f09d08ef321235bbbf4a96aa37f64062b87e8959dbc99a9cc3a43b2829daa490a156e5a347f380b2cc88c2fb01847fb15982903f64c5eb91bc2c632500cc55534469709234c3f75a6a483b122c98f2ef0b43835d68b96284d81161f9dd7ea5f3317da0b8d6d945e8ca1ee2c36fc53b9125 +dd10b88f1b2bffabd48f5372f2087f5042668ca3035dd58325855d8030d3c2889de3d01c4c29309b4af3ee4478de119663358c4cd43bfde822ca3d43d85eb6a9df6702eba7b55321745f8364cf6a6f025bc7cd0efd724f8bc57858035318cba6f0752a04e784ea9b87bbe4c7b6989e66dc214b2038eda8c74866131cccb81955 +d1b0fab56306f78133d466ee8ef5f25e03743ce6f9f0cb3be4daba3b6d38d9d92f3eb55cc4e5f0efbe568da82df2d4a7e2488709ea08e71ad8d6c223d19292d283f77b7d226717363d4472e57c067790c8fb7beaeba402585796df83e7918f88a58698fbc428a2cbac30f09e647b2a36332d006bf1f3cad6e3a3b31bd88a270d +ffea786a2f25d52829f186a0f33580fbc345298a69401f144fddb4706962a2d17281ffd9ece1088b4a0ef43f186a6061785abbf876e79add9354da10ece0764c68a15c60afc504996564a7bff20623197d2e7e92e94d2b1716e15b5fba48f42afa481535f5c861001f7ef481434c7a3f144e5839313c3730f5c8dfd8413abc25 +c423dddf756797d8d1f4c3d65a1870332e1e0f38393ca7d1a1682b68570473ecb473195464fc3d5088e64e04196e83ad79ac888ff490f7ea240d2e56295adf29d069856fd7635069c9964941d2bdc3a171a9e56a67f1722ff9b3dd6493de3aa153db2a8abb97d67f7b8952c4224aa4b2be97616d53b3eee164128caf710ba65d +c9674f220b3a2c58df851f2603bfe4c908e2945bdf89df61d2ba9094e4cce5591c943cf2ab2a40ee664723961a0f353c0bdc5b85088e45d12a7d28336557eaa8224b843882b0dbcc3bdbd766fc2becf05348f2bfc85c4cd472a7bc264bd91ddbeafc8df06e53823d06ef34565439b13d76678ce32684f99ebf039b1aa422af1d +e78177a16356284b786a93ce78a6765e11053d69177d7aacdc500a5eef65cd61a77fc39b07e164684361a378bcd99862ed041a28e9f8ac7da2331907bac701652ac3d1a618d76f6d68781c82df15bb465205c6f4dfb1d7e42f1c2997ea578a37e229a6b8b8318a758ff684d58257ad18e955bcd99872bb3df226674858b68435 +c42eac8e41f303ad0083c1a790c6c79d0aaffc394020cb344fe105a9cc4190170b0fb5fbd81c77edabc17fc7c261a5561f34edcda4688369ec781ef4d486c99af5debded2faf3fa8e96d33999da49bab75e89fadd3cbb8ffbc2fb0f8481370080c35dd6aa0e88aac0d8955c5395b6655cb8bd34417f0686b03dfb332b7b39f95 +fcac3e16eef5fc593642ce3bc0f7dcfa5d3203afdf4d914725d22449eff9c53a56ec94c030cb793c870b78787baec6f8ba18c6e0ab83cc082db8f1d80a5ef4f19f4f775d0581b2c50928aa9bb552c7fbcfc26ca785df3580e53c649690cbbef9d3e9b168ba18ed4ae9144813c09c9212df7a25971e0cf39d16d0ba3c31bea345 +fe925c06ec7371c2e002573af3bc6bdd0db363dfce1fd3e1ab46a53e9a85aca5c41a00a91294bc02b8f672bb001c81f29a04d560dcc1c83a7e379be2e6863a97bf82dbaf58794885d0a5a08344d313a5966a667a7c9149147b90e02e043e8474d8097940d6208da26f7ba17dbb94ed8ea730610a27a6d19db0e852f25d3788d5 +c1552629fa38301034c6cf7b05e27566ba9f370474bd4efeff1448d83d288144dc5a088de234b311c8f9182c4496ebcdc279e299a654a4fbd5ce9d212f4af82a6f4cef9bc22b4e2f05beb2820843d69b1e245da30f501aea1f9c2f498240ca5895939c97bd50593b019e1b05a0d1d5b3acdce7848aa111626851878d2dd3d0cd +e74a8165276844b8154a45f81e0dc7dcfa55d19fe3af14a87ef0c39ae2f952ceb9370a1ccafb78ecaf7278b4470dfa26cea6e901ec0159f3a3d68ab0022c8c2c118511dc681e00fbe2a03cf9431e6ceec99f76799053f1cafac04e94895ecbb46e760d058ec20bd9823ef56d4f47bc67c4fa449c3b795a37f0997e34932c359d +c8326eb60037bf4345b9da19d4a4b0aaa618fce1b1b636d983ec5ca5e7ef9a48295d6fd5d2805d38e311b974f69a5dcca40db2db8dfff01c563bdcf623ce76a3c304dcb8e21df3a5ebd78abdb4883482ef0e99b3ddf998812075be2bbb73e53bc69f93c0c925ef9574c42e660d94375ab0451557934b5d93e9ab5c0160a57b9d +e325d4d545d0c461d1e6cb5c5c88b2fe5a6498a5f4f33c3ebc4251f700840fc0ce8e6b2c5aa4ebfe0d47aa64704656425bdba03ab530ad347e3868af9d32e743c085e48550e64a8846eb6b3e6b57e23c641105153807a22c7b929461c47b98b9980965529fc562c0c40389545d9c93520839165dc9f5df9519812ad49f344c7d +ef6fa5cdd389e45b4a5d2773bcf6c52799445e1a00b80e0af49bf59ff9dcc0b719973775ea3309190f9ed31d59c1e04cc2fc46b5807d51bc4b72e86845de6b39c85c809db14229905bc93c986047f127e7d2ae02184b34b7af72ff1bad7fd0ae398e631e095dfc480592517459b551829f814e989caf154ca40e57084b0b19a5 +f554cd79a676ea46712f4e3d592ad62c12f6f5699ecf30f65046de91c2e47eacdfba5ea7d691802a9a57111070daeefafd93a3efbf7a483f58fbe8bb3e38a20de9c438f227710407c9ea34d6cf304ba18e94f8cd18112bfca6bf7256c02c53446a67a66b5d8ef28f02a52d90304db070aaed34d746906e75aed077ed397f5ea5 +cb4b1fd5fd6ea096c48409dcffe3103a32309bb2ca283475ddfebdfc6d3f21d1a0aaf28c63af15fb94217210d76078e43495bfbdc8ac4a0ca483a4a84fce13c3f24ed69d1225225fa3a39df9327dac09030bdb3191354307db701183acabe5b9f4049a98084711d65b76657bf957ab0e1d51d18debeb386a4a4692ee4b10894d +d729e6b7386227bb2cbda5260a2d6d3c26127d5afb20f93086e44d3a2b180fec7ec80d0e6941b1e32d4a65441504557af88198fed0f8713c7ca89f095e1f3ec17174c6e138367f247ddce75ccb9cff48fb13a62f5feea30dc6dab7d12ed70a5779e4b890200c28171b83ac8a348f4e15027e34a89dddd727846edc880fe8a6bd +d74900ff226b5a70acc71f89a6b928ef282d39e17ca9cd334c4262c44837259ac948b9487ce4be7336b9829b9f48382baec51e5456be045920ed2d32b28b744716617e83003843611e42ae9183cfe86c0b51e514200504dde737f86e70c006b996d2d10ca9c33f733dc29497633364674de14e2256fe2b4658755a48226ee91d +cfeb9020e28f7ac0276b098df6fdd9322178b14087b45b09f0894fe673d6f13b51937a0fb6f4f68ad54bbee4831218ba5923d60ca33ea79c5b4304e773fb91d2026b00a773aca6b9d05de79140afdc7f2f4a160665f9e65398967f2cedc78edbcf8f1c1b9b0a6eb2d9eb43b52e58cb7ab716ec235e78106843cdc5e21b37679d +e280bbcced0e16442aecdb68961f53ef97afdfc030a2606d54e2b5610d3ad6f44165cc2c9500a49b539565f24bbecec5b6bbfc8185c815b00ce24bbe6f61032d30d611ed5b78f8adc5c2c45f82deea75aab6c64514e0cb3602a2b612beff2c102c888df5764e1a7df70794472f86a114ad17107a259535f07d27cf18c9434a75 +f719d169442d84d3858146d5690a18c28e1783be909379827ef36bbbeb72cbd71cd66568f2a015c3b4bdfdd2940fd751af4fc370dc2df02d2e836c9e6c27ddf866b646bc05046aa4a3ec49281d9f03a56897b625d9d884ac02e87bab4cb8e9d875f41895a1dbbd77d77c18e67f55961888aa672edff49c0ba6750d0c97c659c5 +c5188adf4708b4c4e8b5da09939f8241abfbb4735ce569ea05fbb948d34ed13408a68032adc0cc381858a100c202975c05f64d5f240364fc699b4b0d7170dd6b6722f46ca9f464da1eb915176cb62ae58ede202dec980925d9a4c72d55d4a1a617c6b3cef3500ea5695276f3c64610703544fbf32b9cff064b12f959473b5d95 +f848376b6da6b8c4a5a6cd5c091f87aa6861d5f074c4656f1d436fe455e222c778f2f9de22e40cf831e9f2978177ee80e29291ffb6728c7c2317b55e91d9a5ba92e2097a9a18fa975b51feb8c9e720faf8b1595f0c6ec30432660744178ced85ee4caab23727e83f094ece52a12ff9bb473e7c1767ca9d4e5bef3b2774be0895 +de46df8ca7a7d1bdeffd0154a914705de0689253f377ba9d71d0fbb4ef39f37fa76585e83f3f0efe5dbd96d916bc6ce65b5f9e9854740e60e06cbff56b74b00d5c1381c45002372995dd149a0c6e17904b356a6b4991dad55880e146b2fe6d2f5a7923b3ff93d1efd5d832f0bfb3f99d5aaccd7a33159ac6cccfe8d2646033f5 +c05cfce36415e5e276a06631d8bd157702acfed8578334c7a8834404723300d6eff52261007b514cd9d8af7eb18458149a71727b5e6834f019910b098a56be457fef0a1242dfea95d6d9185067e7b1bfce3d398373225669aaf922a8c7f556549f050a0e32ec7d4dd8b60aa9f5ac5136e07e87d33d10b41c51344e7c310ff445 +de846c4c59e11179be5e1532e39df29bf5418a0482318bd8a2e86b85f9f550578ca39d42f4fecb8d449346946d0ef2ea58976a392d5597fa171f2cb0b89339ca30a711c02625232f71caae3e51fc42354307508263028f3008b579180acdb4be0f8871ae4beaacb30776a1889117239af7a523d35477a0a97f1ad09462e9349d +df12c209beed0ea2f3642937597f2552dad5e523e29d3ceefa2a6497562ae2d165fa88a412de4a3b9c60c066c57647dba4b62daaecc6472e8a5494a40cd795008c917af115502cf37bcc20869dcc291de45bb0bf3afd9868949e3419c7f573e88bc04ec813c0efb58b7e8a5993de4ce67a8b75efe0ffb0b019e52e3cae42a27d +cc50771c1648fee05dd7f2b11aeca10f9c98fa92fa549e7d58c9addbde156a9da1479fb99802524f074c666e1c5073896613a3887fb9596e963564f423179d93b8f01e4ea28aa4a0cbfb816cea5093a9514ba234d882587a11005bc9b9f78afefa418ff26c7d9955eb50610f9b334f223a7e3279f879e645a700430897ad4225 +eec6db480d9fa186cbdb38ce166dcb9fbde5378b3b7c02e8cb9b0408cce03f5345a115c1578ba63ada5a63f3a67ccdeff0091f145c20550b6d0681d7b15d85a9127e3609ddacd1fb051958b0f0ec9684cc64d2a489144c6baabf7d54b87208d2a5c90b3103b390be118a3857a6cd8f81bd58ec78874d5376efb3f64639e1af45 +f9f7bf19e35163b79760af714be892589c1ff3a4e640d2a95614e5bc1fb99f9e02780df153bf12b2612c3bac9b8207c69c576011db501a4e667a289f8bf1956f600453ce00b57da6b79d143d69c31bf44ee4bef65a6b0a5c4f054e92c82b2aae00c569be359f40bc67b221edec8a21cf1d5fa2a734dd486c9da49af2e6cc2b85 +c55325a6adf5dbecac33ab7115fbc5502f1af5fa3c39e2785f736003f3f02cd12c172700b8063eb97c7467294ec30a80b523398090f6a6536156e53e9c2f0504fb2a75b2aaa3d989baf6aaf7a9a3f9a80e3ac23b3a05204cec1b1d31f0879e9d3d0a4229fd2af6809d142bc8a9d697b7e04a8f03881c01c46caad405dbcd7625 +e55ec0d6b7f1a14eeb398b7504ed6feda7f2e8f79ef3d1ccc0e193311ff39b73cd7afa873e4e03ee95ad3a8d1f1dc8e1999dd2263bed74c6c46cd061eac4544fc8dd67483a9b15d998128346228151d049077f83a7d950a058c5a6b89953694fa226dd1822c8196ddc75911604330cdc09e5c259ca8b081c14a448e9d1fc47ad +e05c896d23616319b2041fdeea81b8da5077aa68a6a586e0fbc189aecf29c432e46e1e37e515db6e2674837a469bb3f44f7572ffb8abb225291430ca44c7eef9e79a7269209362a7f60c014fa5568a98949809cc93fde3ec99ed034dc7134e0d2e8f28f7ef38ded6a1fae3bcb147de54228dd91f7d88844f31c59882bb435595 +ea2513a18692955aa60455f8fe637f48cfcb64f497063a5cad9f7419a1396c992a9a8e9a55615488b374242caf05a80edf2d871e6c65206a1a27566728af9e4f7581eb1741c0e88622d14a9d3c840ed68cb2146d22995532b820771773b2c416a853946fff2a41136de6205c149e3789e394d75ebaaa9846af47867bff3ac0c5 +dd99490b49bdd7f025fe2ccf451f8b25718d1992339c0a1c62169eb3da2d137db4c8709ea60eca1e590da4d20f737ad582c937ccf364f10c593e9c336859fa403de6f7a5b8de16a41b5d49eafd98a94a8a6b3218ac696e236e46307e20a1929c5bd114516e6b6a6f4466b217dbe03de266e7342bdc3384a34f13116c57d1dc7d +d6366000987a0bc50a837241f9c5bccad07a851d10fd8ae8d9bfec1bdf8acf86ab98b885d16e89827d0ed7522a3e2aaf5fdc2d46e2fe3bde43bd3b8fcfe77de4f4ecf80d6489f12807d57a4ec43deb0307b94ac5e610a29c75810a56b207c2ac8747c5f40b6b112f98c0ad59b6c382fd610818630967bf9d8061cce453086f2d +dbaf7fa3ce31316be0fbfbd2f5439fba81d440719459e61d5cd52d6708e3bdb1c51322f33133b2c6f8addaa143ebf380b46d958723fa9cbd0a470fa1ec34bd5d2417380d5700827259bf7d058306b766d600fcb63eca7519ddea51e7e170521dc2ac5b5df245e5dfc19a3c0b7599cc80d920ee5ff31ffaf3585c7c5791c741c5 +f81d4e3e2ee193d38eb2025316be6b7f65bb6625666079abc6e0c7b7f3258ea7c95c53769112d9f83846dddbfaca860519fb3f17e1d1eda1c88e6df313682f2d8bd6018692865ce0e413c72b1882e315494992173477e759ed05766fdd9769c69f852af3dd385aa9d39cea626b372157ed825bd88df7258a1aaa78a0ffef69f5 +ee3fcccabd80601f017d6b760e12f14cfdc876c8e0190550d32c1f1eb6049f5edd356396314b8914a84f6178f62751e8c31fa5bea13d4f76f79c446bdd45a66a71b310a4ec1c85677288ba0ce73861a4bd40cb96cc896dd839227b2b53a358baa8cf0e70995cd7f66819c00a7f7811502d81f8aaa7a90d0851313f08b63e07a5 +e7bc5d453f823ac26bb071e138eadad94528a689566eab8884aeca68a4128603b771b3fbcdefa6645f3e16163a4b2347b7a63d36aff89e97f5b40894d7cbda43f0dec94040067e88d1c2627245462fdfaa061ced0ac4e9743140c1680b07c107e1493a2800f8abc75e403c4ac5289b59559a9fb25e0051ff614fe3c6314f911d +c6757706c39d581ffb923998c8d11656c261d23f529f1ea3dd5b91482fbc1b5d9d0fafe22b0ae8f7caaac98dfbd4fbad7f31ee044a8d467b590c3166abf56a5e3aea37ca2daf4c1a6815f4a503a7b1b55a3fbcf14f84ffb867cf9f3f546b02009de6d3ccfd76b691e5293240c342550ee13a4141a693071b629fd3770a01371d +cce03e4ce3bdb4c846c1044eacd7a400cea051d22c7eaaa0cb1494e2c35a282b87e0157bb72708a21b88297be011ebe06b2a93c28d1edf61821cb7ad6edd14ea4693821c1fedee39da6bc86cf65c31b949984db16ce23fa23b0d4f9c7d73bef86969173b7ff988854cdcf7a23c9b2e3ae8bab8860d85a5ff004349f3b74b4dcd +f3ce37a66647d5ebd8781e14c54b25e738ab57df1393db7bf1e71b0e5c2cff7e1c9aee1228c2047979a6073326c56e969577f196e58264cc3e95addddc871beb8c7facf010236594f33644576934e024a3194f7c168268b64f7082ee9cb96cdf6bd834899523841ffa8694eaaca9c2dc48a53e02199259c77294e2063664fcdd +dd5df28cf7821595a31fd36906f6802b3b402bbb1ad9870cf92b64acd08c8a2045a4ab03ef7cd607a15d27925b3974ea3a1f453c5d59c744343e7686a62737af11557bdc6862eff77c9341c988696938874064dc0b0e1212e6e460651c05edb595d849a974cdb58c498be6e75a8ee339004f121c4ed81b50e88bb8d7cc87620d +d56377fdba499c3acb75cc81353de33f5f626e85d74b9f72fdc0a265b19a7f4b34295a3aa78073097ad62d38575693cd8bc5c6306286891d201e5958c686ae7776a2b3d7d9352fa536f415a71565ca2a1637ce6c1c6dcd3219852a87e865d5d4e018269a20a10b4391cfe8216d2d8712174e1c6bd2d3a369dd005c913fb1d9ed +c24d97dece5958111a0a0d8538d1c15e282f21681a47f5c66035267a89e57d21287000214b069c5acb3ddf99e9ad4d18c02b675ec1b634394901796507a740c818b8859e6e74bdbcd433a236c7ab511131eba2d27414502507cbba401311e9153a615db6fa904d54d415d99970eaf7aaf3a265efdd2021b560eea01b40c1a0cd +c65535ed408e69a5928bb27267ae53024e6ea2a32867212a914b9447d07fa6b725e4337bee9b7b7ff99e065248848111b08d4bd028533cc9420e54801ae0b8536ff3659f34eb9062f1469d6dbd22596ebf993f89e35cd4366fb3de63886192030c477ccddaa8cfd1944ed3aa2288d61d7f931e42cfe939cde98d42bb92c48865 +ca8d20c285a7f844aaac144079b0e9ee4c92e160aff97d298959514223f85d94658219eb8a0740c7c1b59395ff6e57c0b9688e8a843d9f75974f5fab5dcda5a0ebf44dc271c22f0138f1268de1fabd7088f34f181c20c58479fd5f73b36c36b9c77d1a02c3c999298470dbd1a4edc324e3478220ecc4e11d3cc350fbf20ac525 +cb1f812e799aefea75f7ff591654d77fd43706de79eacd8f4972e4a10d433c74f66fb644c7a53b09ab8611daaec1b8b158995d1162f5cd66468d3627638694f0144500412822685b72e9cc4d0f0310cbdf9422943be40f675255cd36a624dab1635e6257ea937ec0a9c2218b3458b9f807bf604639bd3f2c7ea9df24bf7f9755 +c9041cd6b43bf14ef4fe6cd495f876bf7a3da054e826570bedca2593b715c5e6f02f5ad5703196ab717ddfdd926dc5ae1f4eb49f054b8078da6fcb41c8d828833418c883451e944bc1f62a02e87423aeb84f52a6806d6fcabf42ec19ba3e023c216d57215c3c7d475065320677210d19f1806d08fd6a3502f8e157c8ffc7ec8d +c5961a4910ba30ef276b27337bc4adcf01c74a83189305f7be816887901c6eec46d204e813e3d4fe85e812639403102dc00a8e2d54c858e54d69eb45076ec46b826c9f6d9eb862a5dcf168fc71c84b1ae6a58677fb16eb1b11f37e0844a84b8b0bd06c33ed5b1d61b0855cf220429803872218f736089e7f0627927c01891b5d +dcbeda335b757bf79323762fbb7b849545bb717052586afa644c0788e300c07b3ef64437ee07a0b181c83cbecdb49b91c4020215fd88302a232c8ac46a0fc1c1a2fc8b45b66f8e8ee21135b1f186f1faab41ece733401d92ec4cca066d6a6490d721152b5547bac7cc4f1027ee7c6edfdcd8ed22d04586fd159cff4ce970b245 +cf4169d4412da9494e211cbf5d25ebee47e7e48409e3b9d76b4bc6da0f91836fbd40b4ede0c50d05a63d6184c9495dbb608d3e57117d086d30e35b121acedc64dc75c5f7c760cf9d1a455f171a2fa9864f404f7188604a92301b5fad6d5544de323a74888906b6177dba5a643ac784ee4eefe15d6833aeeee55cc9a0f6d699b5 +ee2113d74d47670f7313c08e615fecd2777ccbf355bc125ab0bc48151947af19b99f2cda5a815d5c44046e74199595989d1ff84205a8a2c976f9e09ff0361a62c27b3575d1a53f3d3c9c2681fd9528a71e22bb630f9ff2b9ca1a77c54ccfd699595d97becb8764cad0383aaaf908368acc311b43980cf902885d0cb13eaff335 +dff036be4f36093f2e20781547235c6b88f82401795e0cb513d74e9618236af81d9daccda3da9c4a5272d2e10e49a776c7baf5f2aa40fa61e1003df52d603a6abc2484eb807588826d5027f5529fe01b6651a71dfb1ed23990c7ad12a6902c71282e9083fd6d33a36919e51b00d10a47582a9dac65b9d192269000c3bbdd6cfd +dc0d7122b50d0b27327606cef7fb6380d0e7f7297f5076c4b4de8cd76ef629745d2bf9bee4e2b1fd8f37a1cb11758e98d2f2e54583de2a3c0c339a8bc8d013d48d5c76297e12e18d03aaa6f242defd98b145f5bc37224c0f94f895132b6791392e7d598e0b39c2f9badf8631f19325fcac3b8f8ddc655914ec249cfd9e0d0e15 +ebb816b31744578bbb9b10c8c0217de1c20b0ef86b5bc6da94f5708d0140618a56699792225b3adf6e9a02b68422ac0b9f8bc5f676944b4bc3382059dcb33b5343e2bcceb340ef9faed9044814c41de3cf862e07a2bf936a6e8176bc8217e24169f9fbaf8c09b321e349f4d2364d9e37096ef8f62e0c0ed640adbff7bf7b0135 +c68591f3244def5bd01eb6f7a257842fff85f59e2243377e0d265f1f1b90e478b563d5085d1982d96ab881793e195a168c468b50c2c16388107761bad1278db7529d207c5a41ce77bf1cd4a5f6b16cc97b5186f821b15311a07ac6ef0df2994372f2f52c3803ccdad0da78ea6e7527502970e09dd1ae7ef8e99b872beb9f8045 +f6b4a1c781d759e5f4a13973e003264c365893c9f181e5410af0820d57ad417039913bcabe466e43e7e4d66d79fc564a627d3bcde846d5ac6658ae09444050515953337a9398bb1ceefea37c72c67f09cc0ce3f1a4091f52834003c3f180ac340819a4fa0e9fbe074f9d0187392ecbcd024f0a90649759ac83fdf7e77593934d +f6e7675f852d318d6b402d410762978cca8588326d5bbf84ac86160e03c426d90ce167b041d255993eadeccf331e7d0cb57fb25878da293cf2b9fead61e9e080f2488d98e96179693f4492cfb4b6df7b24446687e1b880356779fe408b09c07ae59fe64cd4bdb209dd93e37d6064f6ebd7f0b5d3316e77c916e515d608096fbd +d9cc77a38c2e2c6ada42e24580e3a801b85020808778cf7956f90cda127aef2416e931aef46688ec937d9d57401820292f1b7ef0b956a9ffedfb4fc5c04f9e582fb527d7e09d68ae5cfe1d99b47b603302a89fb5b933e18e4f0a1fdbe591974537f59ff2ac171bedc72ae00100bdc4891441c2767fd70cc9917234cb6f7910cd +f29f0718f61441e6a7fa1968060a4624c4e038995140029615e447a2ceaadf4faf0b650a448fdeaf4d2bd8a3467fbfbf1d413dac1706b7d4d345daad253a8e47bda4215bb71898c7b4859dfdf9011f4f14b76be402efcc22a3f65895847aa866ecd65492a53e7b024513878f197e23d16b6753655c7f2f67d1d5a4df6112e87d +c38400b70f59f672e31bafa81bc5da25f9eb83c2892534d863325df19d0cb4d161db7d52e5d96ca6d4884cbdd47f8f95a7f59f087933df4c687cff3c1c09c527e559a50674edad1f798b233b3a9e6bd0f1d2e14933ca7d27910e4cec9022fe6713b6d774f624968cb2f8a146c5aaf48df2a44171e90c98aaffc5b45cdd0f5295 +dbfdf8391f3f46855b0effd42884211a069a720eea40b4045e05b3f7b89350b3baa9349542f5dd48e6c6675799ad85b7ba29c0d7163f9ecc8a5f945e9ab62cbb3c05f018e07bd736b3d245c168ed0e7c565fa8df0dbf75649acc4a078f625cbe24d7d102bfeb66971d97774e5a2a686b7484260e762c2cbe8218412b255cbc4d +ff1044955a4a46fe88719b98b4fbef3610210a11a00f28779409e52a898a2a62d383379e3892ecbd5594fbc4c54d363f2030ac48f0cf8031904c598d494776c399cfeb0be3b0b376519e82981cd88d0dbb656ea1896aafc998a00c33a7e8e619fd64838b70bbde315812ed2084ac77af17a5c5737cbdd211a0559f178cbc796d +dffea7b7cc8dd939086609c14c85234851f74699f5df1de82d8f9052f8d29c4e2f5af05fcf1e0111d0da7d216ce76366684271c14e56a56efa08592f7c0aac245aa1d4a0acf19f921884f50cc320fcc76f1cd094692634e3bd5142cb588e62687705b236927f77e4097724c5936523fdf6633a934efa57ecc0bbb109e4301575 +fc7089d2a8cfc5cce0d344cd5ef8b83274f0e49f7a805299bf8adab3e89a074d9daa62f7ae3b8127b628a11044a511061ab08e7751e9603750dc5a5f46a46735b5901c118a2a839d1232d2cbb429c0a7588847daf657f367560e30412e984028bba9616754eb2f2dbfaa3ee4550ee81898d933eb5c4339c1f126bf9286e7721d +fad5e667ecc443e6caacb6ca76599adaeae84cbcb83d0713eb84f13dc7fdf4f0d208ffe47ea4a1d67375df6a08cf13067fb8bce071c39a5a75e94363964125cdc689e499394d3c7d6f0ca6238668024221f82817d132e981c72075db853262cefa4bbebef031efa99dc6ef5384cf942c6ecf0746825c9ceec4cc699f2d4181e5 +fd1b4d7018b7346ea508723e0a7d3960a8828e7789230e1cc749340be4c93b4f424f598b1acf0d16dc515cd6ffb9739c5d52d6e8e9e570c355a0dafef9dd7d61071b0b4ad1f9189df4284308d74c34eb8dcc2d9b9d8fe66fa96b0b221881dde85a8583145463d45d7e1abf1278da2ea8050db5173deb108d12c70528d9c4745d +d58a4da763089093120a6a32735137d1ada1a5ee779329ee0c3c04036ad92f36ac3d4ece8e47e6f3ed86ffd47e96e36c245141e64bc20a825657fe0eb15ca4dd9456e59f6769fb3545f5cfdab573f9ac9ff9ad1dc55f012589cc6c58025df387e050d52ad8946f9618fbce898b651c8fc155827229a779a6876e92dfb484ca65 +c9086f19fcd869343b4a3c21ddfc79caf54d812e21049ee968aecbdbf22ca5f4e211ac94595b28f9f8a3f7f21d5a7c95bbb92a5baa0906ab3ed98694a9a3e40dba216006180c472e993fb1674cbb02c5dff2e77d2f9d03323bb0addddb2ed040c1c55599377d7e98cb0386cb2f95b8f57182ec2b982cac39f01243bc0ad89565 +f461eb483e0ab79a1a6d670c7613f6b04b6f3c2ab1bf12bf20d108f8c9234e1fdbd4502bf829be59b4ae68bb90fbdd6d5b19c5b84a3a512190adb31df2a4e29b5fe4991ebb00532365ffcbf462be7af9267e06c252ff251093bb6a442e1c88a0936aeedd25d99513be8af23447eecb1dcb06ff24ad868e44f53c790feaf4ffe5 +cf62f209d35a652c0f29f916da23634d32148391c06f3e9691d24758b87fa9dded4cd75928a2c4f3a097a0debfcb6928405e50f4508e16482c30f4a6401e1d32517991d3e13acba0397fd02483705d3500f81cfbfac3c4fe75d755999a9a6587b1ffd34f71a8ee827372616aaba8d7e44532c639c104993815efdf23b86387ed +c355f05e36c6438f1fd6ea0613892c3b71931a3af6738797cfc8fba634d62c69b1a803f4e779e3581b1b834fd9ab5f6424cd08f5bf242f71435944a2c31fa93bfc8ff5baaf40f5e378962fa3c10cdd5a1bc8dc0a0ee910d6d7182f5bef59bdc4ebea9f46108f0c78192b6cb94d8e259be4667c7ff4b8b48f51fdd34600fbd7ad +e9704819bdae06326676d9c36cee870a503273e9e450594b52a16ad584504f09fd19177569de2e3c2889d461257b6e69d323ddc6534a672a999118967bf283b012fdf87d9301c37cbffbf49eee882aac5dd871bc137396e9a184f1f11105cfb6b88fb8665a861f0894ea4270fd93130a382b938c9218143345e3f7fc6d24bd3d +f935d2e497d834233aac83a32151b1f19adeddcfbe5145a882e0faa6a53324dd21c79e5677eadcfe93628a58f70bb18d004fae06197b01293b3d09fdb4b7aa0ffbf7059c62185fc4a30cb957fdc13062583c3ed2f4e4588a7d63056e7c2adf47f6467697c6ce15cb542e92edbe132c1d40fd56aa4de0b107e3ff1582e5c0e475 +d51a8b2cf9408add3bc549a140310d4c8df4d2bc68ec35306ea146b90c2d19197afbf54891a240bdd1057f3d8238578ea1eb2e7c0b54676e4b53549fa074bdbcbe794d9084810ab6e0b4827c739e845912f54839c37031482e5953f04ca7b5c39d28c7d97646508675386085a3b59b011ee2b8aea1f46c052753376fe5e027dd +f7048051b96422dd7f07e4fe6f1b70b95aa981f6136cf00e05f8bd1c90d54e425bfecfdf1c5522ac89b10419f898bc1c0616ee8bc703c0dbe4835ed1f56ae159685535960e386e662ea504c7b9bdb1ae7a0cd46e79eaf6e72e5aa60cb58e1c91bec7258677438198287296625f65c8e77db2c44da948d8a2f523b1e65e1f08e5 +ef81839f7627a4798900fdaef895cd619689724ce0b8b3af8b12711a1b7c4b89cba3957f176d4a74668a7e7eaee137f9fb144c96355e1cc7170c107f513a2a09d3b053c8b1b6fc9134c084e5540b2f698190d43b9a1bbc0d0cb77d3c526a95eb5115281fb66c3e3c569460d701393a91e41a1c27be304c6d4d352864736f791d +d06d19436af8376073fbf7527fc3ef4b54e6f6d7323cb3fb4de5547ca75c7aa5a975665c9eb6408447eeed168c75a94c24bb7ea1047517a2991d204a10fe798d24e57d0d907080935492fe3571aa8a97533d0f836ac2037023d22ff0674954a43f144d5ea0755cd6b5a64a5f9da16966c1a40f757081a59b51ae50371ccbc14d +c91f81ae46dbaa65df1a6a5e5ad6e663575559384d94123b2b25c73b67e9d80a56c1e7e503906b87d04534b8d1e0ee788e45458558b4aebdfcd4054871c00ed3f1913e25c154619b787d62fa362c92242189f3b12ffb89ec239c20fb9852900cb73c5b6aa681165f6692321078aceb4da6d8c6753038a624a65048a60903e72d +e2b88ee5f593780e9536660e1e277047f5f00f2507c30923f76355443a88bd194546598aeba7d8a594c461973c066c9f1b72514ba669678a85b5706637ae059459d99a4d9e1bf1a95988226df3fbd51b0c08bf65ea092870f902d734f2326c1c82b28e32154b7044be05a11d4ff9505e8b22e991bdcd295fed0d7d520ef59aa5 +c51bae95613c3cb9ced85c822f9f63284b4f69cd5806e5f17e0691fa5531d3a83361e042b796f53667517851bf533915ade6100c5e35e571fe62186af6a2f6b111f7b006ba1d2dfbe15177f0df69bf48e59bb15c38c3e5f2adc861b99c3ec18e86cc2ef60765a1bea21c66a4a93f5ca5c824a33e3df049e2294a851e607d98f5 +d44dd9aa118e09e71722661f274ecbe1dea8195148b3be5788e0581a67b10c54fd565b1206442dd2e6ab50d0acd466d4190fa2b435c93e6b3599f38ab8ac197a97c1b6eb85ece86f6ffbbdca079f844b9e7aced5a1362415d7952785bc3d7f7759cc23fe28b1e7004ccc809956462a5291d03ea4db7ad19c160121bf81b6ab95 +ef78419ec73c3b5c017aad711d0cb29aede2c53c6849a804fcfdd1e4e8a32d26e5d024f3f621e0053c03fbe25ef5becb19acefe10688585b80d1504f0084ff606d37b8c630e73f15736dda94e82eac69d73b1fd69ac9c0af1343dee6b43f512d93654a9559331b93ab76767e5437d42e8866b68140b1c7e8a8de2ec92b96d175 +e0b9a8df9507d8acbc32c9782d83d3a67e5e9601c155794bfe29e065a4f3bfd5c923001a143473e1cbd5d9820b73bcc1014bb1a7381ea8402a01734683529b599b19505d9bb7eb270c9b64a57b98f97554ff8380f79653ab19bac8ba59bc057463c497239831384ce93c4da48c0ec1fe94403ee965f3856425a082d5bb9d158d +c88f3d02089a37c3ef9de421da396c22884f1934cccbf6a603eb689c1d6d503cb9af8f153dc2f2b4a57d4e3731fd0ac69bfed081027d0be77f299903ec52846ee784024559b5d13ef76dfa4b365d08a6fecb2fe5621dabd3963a3ff799f1e95466633169ad5c5ea044286baf5fb3a19a2a7147affcdda544c1061da877b978f5 +fe6cb780781593d1e777f946121b55f15059ab69f8c1ded35a09e6c29dc4ed637bf0dd3e11a7c056af7c7fed27e98bd80a5fa2ea7665a82b8381261c7e764f02fd5f605c7b8059161cb1a1e11f7632c90d417b460e32b3ace20a6948168ff52dd64f5c17a412b7fa72674baf8c1e24ea62a8319b3533c4dd04b840083179627d +e14376d91a06128b4239141f7d4b1a16847d475a02660e0304396ca40ad93b994c6d501db2cc180f466437841e76f798ceb5e7523ac41b4237064b2b31245df30dbcb6a076cca82de707e1b45c8892556f9fce262ef24169cdd7539c8ec04f497f5c4b28262a2622a650648ad9d4ae5e1945a443562a8de81518b22c42bb3285 +dd6496c4c984f5305b5d7e114dc2184f75ed627180145f331049bbb0f15e14ad2fa74ba7540206b61ce364bd191230ae6ff2d8c25d378d6ff9e8d08e4972a015b917b43ecd734d6defd9961cfe7ba50b916294c9e0cc686c7a496eb5f44c98c44ab974af71be0aa50f5f47cb902a6cc004289ee1e882f9a71bd63ca3d1160c6d +cbdab7643480f2ce10c7f4f3effa1491d7eaf45109b5e7e188cd5d8cc3d6f17b220d774844d4d130edd0ace88a8758d951187405c4dc67dad60c15eb7a2b7695393459db06832e96bb017623dc617c0b916484542633c5c68c0bb44ebe306d9ab1d7e33fd50e328cea3f256393a822dedc68c8af63388462b1e5b2ad9b72cfed +db561231fa1ec28360b09c579bb5cf6d4a8038139fff0994a34e325ede4ba9e41cc65eb04294490880891eb4a624cdc25777e8ae54cc65642e3e986d25f0d1d68450df0bbf52f2b0ee5da9769b6872b39abbe87dd4ebcf56f16c4f8c59f7b27d49e84676ee28980a68fbac057e0bbf69a5414859aac4eb110e18102e4d356d0d +d13ae235284d459e4228f01ab6c8b9ca0df6eb563c83471c32d272e8bc5708f1dbb853d4a225d019b0d63d244a79bdd9cf83152b5c568a5cb378ae601cd96864cd2fb65a1adf1e0fc8cef28c367f44705ab153b86018287fc73892221877eb2f544da6bd09ad2d9eb5285978a49fb3536b8ad70cb0b5dd96577b4d284ac5c1d5 +ccbbb29d9ee1e4f113219a526ca77d70a7b00fd13f9ae423d287c8fec3fc4d128a3f29110b87933f86849161f57c1b72c9309fdcd52390535eedc3b18e61acb6e904aeb4eda536a74f53fd02c9fa903f2f60532baa57c26755168b02db0c3cd311fea7b833ef308be69e8e4408c23eab0ccd3222231a17b74438a8a937746e15 +ffefc0562538685dbfb1e3184c5c855dd0a04bc340374386134f756fcd52deaf24010cd012ea90306be7c11128326b8e940a441ffe90c81c7096e11431482a8cc42576034034403b8a5691d28538833f17313e610558be716afed80807ee29d20b309106c06edd2e7cb06f905af6fcbcb5ffd41f36acf88170330394db4504bd +e3081868e6bfd443207bc3b51e53884770f6dfc227f5c4ad5aac48192c838b7d53b753365313afe4082f5763d93a9362f362434df93b06490bc0df7ed1a3e69811fd8e2f2daf8093ed7a3c55744a8e2243eff50570aeb50180d9cad962af13522d80e562dd549840102e4af3b654f62b29a8a035d59e04277e3b8204989feabd +dd467258d247ee309beefa0333ad4bfd4acffff39ddbc44e6cff2492c65f2a9cbbeb33b915141d7361e579ca387ef3e55105b39db94a006dc92f55d104b29b2d9cc52342e58ac426c5bea0c600845091de3ec35bff5ff3e181c8c13c763ed8ea37d5abf8b39f4583034cf575000216c48d56338650cb39a4e1806c7dcd5b3d15 +eaa24e93d42d27e4bb64120d554c2ee11a095f0f9ff153b835c94e9a2133812d5ef3a22be995af15f6b12b7288c048a6fba834f4698e77259b5a1cdaa740d550383c2c0be7fdaec742ba71148a08d4934bc8e719edc0fe65c32ebeaec3221f7566b9f8f4dc076a0eff4a35f675852a26e46914c5bc2f1012c8dce0f5f6b71cfd +d1ef6b9fe5c0ce5ea98ee2851163b31dcbe3626f2c61e0343c3518d407aa23e14c1d9fb268c844608dc939434e54a5c20f2604c1ddb5fe4f5e71956a4114021758963fab0f569d82a333be13da8f80abc81693de7fe55bec0c53bb6f2a92f9ec80ca756367aa767b39d5b28fa21a232e9f524a2b08586e3e2630c073710083f5 +d0898926fb912d9a6a570a895aedba60ef0f47192b21b7ec097f40cfa4eb92ddb3af30bb55a8dc66a74a68fcc908f19abcd9951f06bd9ea57d91221135c90bbd191b53c03296b8e5127978ab4a7538b3f1a975448474b2895e24eb45ad71bfb24de5b98cc1858a25d1d41a0ae575b05db820aebbfe82a1b7f362509731780fc5 +c77eec2c2dc7baa150df52db49a9f9d624da0cdfd2f20ae97d27e948321afc76aa9e3453dea6d7decc72c8d67da56f57de1874149066b20726ec74b2dbd109bec0fa05c735bcff108ba3e966f00f6a5bfe868c5b74a7983bb0d3310b80b6d745b7a288a73ee40951329aeb18f1b5054a4148a89c7cb34b0f5693ad7e7f29577d +fc417d0a6a65e7a90ca52a82a7ab97069e9845a248fde683451ae12c6fc24391063da1dfdd12adbf2f6de878a47ac0954c8bd6a13129ba1aecdc535a16feb591ede4a8dcd5b0aa9d40129dbaf29879af5debb7fac908565977889ea4857c27b6fcebd8f0cec0fe5ebf1b0f389205ad4976726aaab02045cecb7f3440231f98ad +d3339da1f1643b18af3aa714ab2fef6e2f229821d1e9100261f4f696b972af044ee21a2c0f3f3f0cb69cfbbe06409057a02e6129a3e6ddadefa12639ca150eb9ddb0a2e4a0b5697e4160de6d885061d71cc5ad6a19c7e002078e8ead1348a3017758cf3cad68d70865ade96f3334d708a34d5931ed105cefe0544e78a4388805 +e9065eb79ee92dc6837b8aa61f7e99541dc966151f34dc0b97506a5666090d58c815490a4170097a4b5158aff94a69eea153561c7e332b387c42f3563ae81591e908b0e2f4449c943e7586bb4aee61c31d9640f440d08fc1bca84f8575e097817984e803705a513ac3c852b702d7675d5782e365eb76995d1ce292194039370d +cb211ab2c89539b83d3b4f8ef0edc2e2a061dff45c19b8e25c9905049323f59e42108359467529f94df66006d2b9409f1add75c7be360e29805570161d3660c96038c49bf576dd84f6f9b12aae23cc8bd268ee48c29b5fd3c13c939308214c759c7afeb89465b1bea95c292a0481cad727acf3020a44cd639740be98cac94515 +d5963124a849989d338e6ee7ffaa24830b21fb0b32e6313e3ea77abe09b62ea4bb29a31c7df9c38fdaa25f5ed00abeceeac3c79b0c33dbf19380a9a88cd6cfd09e5bcccdbdd644ba3e018893800a910f2e99beaa7efdf3358ce600d20be8020dc4168647e9a530ff61673bac47ed53c63b39e9964bc542b797de0a7517edc385 +dda885206c316fb8493450432e705e2f202dd4d5a35f86bf6332df0d50729aa3f86bb71ef78d7af36940a1add9f8679f0b8b67e828755191f76ff74e1b0530a9a2fca1120b32f28c3e73a9e51f9ac3be261c91919d936c66e2da8ef0b23db3c9a6b2c3e1d71fc634319e99e758513396352fbc9c978c3e8746e9dc6e943655fd +f0b6bd708eeb9a153389eb769fb6b140127f876b4116fc7f72dfe4e3137951dbe9190d6f76916dfb8dcbe8c8ed02848386d8d43298bfc1d6d6daf773156bac1cb2463ed1232902643bb090eb604c812de60c1515482bb3217660e11eaab25865f375d9fb7a5257c80bb5019056e233bace203cb691fa15831ae1302901a7e8fd +e6e9ede06461fff5f9fa150353b9604229649e454bc1adba9d30d58fae3f9bbd45b45c4a257e71163c9399a1888741cfed9ff01ab8167381e6f16e6e16cc2aad73f6c8c30d1d0be9eceaff662984aff469d85cbe852086beec64a5c7a2448720b384b79d046f4c41408402621d2a676aed29d24eaa99088d126e947f9e240475 +e99b898150f7a8a2d907745b3cf293f2484957a448f480fa2fa9d1069ac64ee0b34fc1816558093e14d8675e12dc416732f6102ec9cff519315806c2d75bf4870a2aeb20abc04717a8246b3ca56ace5db90fc60b820b72876d92a6a4ee263050d4a529ad29d87f626f5e9c4385ceca30076eab6340e31adb05490e3fd0228ac5 +c2a9ae48163c80e187b63785aee50b61cf8cafa1f41355a404b3bdcdb1468318ed913fb4294b51e7301d92f1970dc01e4320fea142e29cc8c10d083a6b6523829a13a762fc6681ef0622ed11d81108fa814b989eb435dbee63e025f9196761850054ed2148c07387a5f8f20f6623f6531b4cbea6ad00e8398c3460edd9c3b48d +d5b9d5961ae8595d6f90402dd03cd9af9194ccdb9c30db8df9e4e3951108f739a6b095eaf6be0a44e681aae508aea83ce5aa3875f72821a8ce50086c91f08a731de573e52ba0a592b5f8e3d92200aa1b742f1c19533a4c321873ad2c4b5f5f24b2f6d0ae92a09108735c0a8795b476b92a55bb65a86fb142318f63bedd26cfc5 +fc0e95da298f47b4c5c200cb2cf6c8250297a1cce4de3a070884413f6403d2410277f934161acf154e2c2987279f1b8a1db936ab1232dcf00e02926a218388f972f4fd47a2299af22b9e15b9909154c0b615929f13fd058f331bd1d3f61291373027c965cf07ccbe762fa5249855ebbd897dff7c802bd81a7f89e5408b4a0a05 +fbb36d7d5e2598ffbd50b3ab673e91ceb8f99f6eb46a756396bd2189905426d492acc0eff5245cf16231795c3e3e88bb11b2f66c7c5995130f7679072addf04f7cbd9059755ec8c3163ee8390bcc1023aea55b16f85972c178c46600a5bd20c8aabeb7cfdc9731acb2068ab311b1665771d4b19a8d782fde357d9db1e6828095 +cf448a3d3b21c41ba1aee82c0d424c2ff6d5afa1bc2fa3c82483c0b60ca0ff0fb579cf87cde23daf83b1077f1333aa5f51dd14ef5d3c276cda122df9e79e4156e16f97279b054fda035f0292e0098ec65d9ef02f2c6076016969d58e1f9fb671e356a956eaef3b449088b2eb8443df2cdd4fb09874f6614328c41e5ac0b67e05 +d3f9360e3d6ea978fc7d18f492ac4696929fdec822744c17ed262748e6bac0547633d89bb9c4b34bbd385253f170f262a22ec37d0f68fec97a193b23d73a649177864d08504e9f952c5d52d831b0fb7a2444db147c2f1c4d5d359deaa19b5b335b968d713cedc0d02dd7f08537bf3f51e17ccc440336a242195c239f5e558945 +c72746e4ec4cfc545d4cd3642a4775a04fa97b2e502f52783f56f90e7549b82655053833afbee2472fa7fce36161b90b8463c22511122e63f9416e075517e917b475d6c7c66bb61dfb1a82391929213e05127a704dc4355b563ba246819c48bb8ca27cecb6633aa89d8114e8c23cdb470cec30ead9f9e815809e7cd5bdc51f0d +d2e429c50f73236e0eacf38428572263d1e37d3ca438d9a4738660097c26f9fb7f4c5a28cfa789465a5961c8a81eb6ec5ccecafe1022fbb5bb1c7bccd93be66f1058ce0fbe48c50d961744f507cf4236b4cf5aac01159c634d831941072e0ee1509c78bec8a8d8867273a5d59cc772343c9afdb86e6a50a8cb3bf1e65be1f405 +e0c9f261bcee9f861d84c726717f65582c17a3db29d18e1a5e4b3e5cdf7cb850de9e9cd663c2a83a5ea9282e255c6003b77eaa0cffcbf0ea1d01c3b9eb52aa0358cdb52ef08af713e077a7e4afe78323ad1e0e911209d3e9eb23cf1b4f9fba7952f697e057a2ef7905bd6988c7c669c317dfc2e5f960eb1b5c645e1ae9b6bf0d +c62c8b51ad3c9e9acdd33a4f4ea308e6cd444a539af5cda31c40a39769d2bafbb632f60272615ff1d5829849ee087f0351f7ea347fa6984532dc286ff1932871c7d11dfc6050a02633b3782c2a0c2ceb219628f6a638d14d8e438908ddaf6c623bb4c69a4a5cd313cc8d17126bba96e6ec92e501d8e81b836653152b3c3a9ead +eb161956621add40a0cc0ca3f3bc9a60f2b0f6a2274f4038213e3f0d288dcc5066ab3813fb42687196ab29d76f1cbfb0b0be7cb9606207a7732817a49230b60b9de7fb8e77a20815b83f84850dc0586025e12223f82823d6daa6efb34b8213c2c439628e81850110815d225305e84165f1502239ea79544d7dc322e69aedf2a5 +c9b557ebd4b4ded4aaa97bf4db989dcbca6a741d59cca239ad8b0121c35508f33a321a1fbb9123d9ba370ab69c70a4032f34c32af2d6a54d7e312840171ac11cd663b5ad8df1d7bf6f9bf972155509c2beeb1c65a0a7b85a857a66bfcca4a62cdb4156a460e2d6274e8589ad83431f824eb51b3f06522e52f7c2d3e93c541b9d +f17c93e94c7ab2f777f518ed702a02b4b527c8d21226a7941559475beba02d7e8271bd3b79b78ef5256b094610e4345fe43802210d2e9d072201436933fcf3243323b7b708f93ef223f2eee56023307c0206979876772ff1c302d9684def77c5c37beac1ba407f1c92f23df7e380c4b3dad03b333f145293737e48c6e4c29d2d +d677d7f7b547fe2d6e89c506500885bb6000af7b109349faf06cd588a829ff62b5e5f72da766cb26f49c41e40fd743f03b887998ab0dc0d691fc16073066e3a7d3bb562d25a109ef7228849be098bc41a94d1635d61d0c07de82649b597eb53384b4008cbfc981cd2ad32ce65fcae288c6b57e8410ea504e68d169e3a93ad3ad +d2738f6224131eaa57bac0cb592b5888cf9ab32c5ca3ac603f00dcb7523bc766033cca5ed14e1e85acb26e537b1506bd9ede1169b6771cab017e4b65fa473290a2786ddb0c065dd9e13d3fc3274c280f7cb99f143a3e2f3e66d3d259c9100c7852aafe78aa36b33545241a422734d1cf216c45a1316b7f5280656a768e8a5f45 +ec9e5721d7fa361c5555ae29c7c53c91735b9b9cf971dfa5359f7a7684ef737018b70235d9f856766fe15c87829fc13a0cb22afecb906af9a3d098673154121ae0556e17e94b05784ba4c3b7c0adcbbe8c595c4cab7c82c4c8dfa9f79c15123af3d9c0862dd46244ee60cce7861bcbecf41e1b1d39a708135bf042615adf3b5d +e61ca49b6676e6a5a59d07f5fc51b85ece0a7ab69f0a851f71688f3aca1bbd19b4cb9144869f8827dca9cbfffc59e57cd8729bbd313b8c1713598a584bd9d2f4027c6f88e24bea6738d07b5adbf8c0f38785aa33b6666664607acc77f4f3fbd350d0bb51da7d2693f1fb35d0c61c269ee5f50414b1a4441f72d97d429a6f4845 +f1ba2f7d8f063535c811c0b268d314f93340ea7c3d418928cd5016a2e8224ada2b4228959e6abe7c5c3c9e2472a5cf5ec6d21b7449af0bfcb00331dc64c03be20d75f7b29d2d47642792bc9acdf2f1647ad453fb3e63301385dadc8472048fc73a32e7d3fb6283994a322f7ff6cb8a419886c2c0f700ae704f34647a97daa8dd +ebf53f293fae2b16f3d0a34227556cc536f7f83542a627b250a4b6e8e41fe8a7a68fb9beeef8ed233bed0ed4419eb832a6e698d0ff6b7fb95617e2ccce0561a2b0f124b15bea9b59aaf86ec04374d7942bc6a7e0167e5eeb360fd6002fca0dfc7935a8ba069d47b74821777900ed205980e1b8182792dabeb5858e8e2f0c35d5 +c6894fe616cebe6bd407afcfd26e4ff2ce32f253bf530de41ecb645f181806cc3d592a18024d67ddfc1779788b80dea06c7c4c29ce0294a1dcdc76a30f173daa97c55a9f34aa0cb8f5d848a5f2f706cef4eb515397d4eb38d493a3df2b582d7644c3902b780c93f0c5ded25c50fdcaef8358139741af17241ff861f19a5cda05 +c044d81f9543061edcaac544ecff31ceeaccac638f14129d9df54c34891a9c2482766445a37e405493467ed188b570ed1e8450e6750873170f4ee3c9c29a519b0f17bb935cc74fa6cfa583f6891cd935cb8868068b5d76975074ca7d4c6f2cc0156a93e25c5eeb03d5fd6d7858b599f15fd8ab9e6b5dc22ad1a302f96775cdd5 +d9ac0da9f7b0cefde928331c9edd485728a4e4238bcd2c4df7c1ceef777df025a6c94c27ccdd49476ebfdf8dae75603fafb4563ebb956a6b73b381dec4d414d6031d3db06360ee425b7f104e14b993acf1594695500c2ef559bf9f569e3e33232c5333814d1060c696b2c0c58ffff825cd92ad1c29bdd4e0ae4b711639bb6ac5 +f2a92c73a5decd8e1e36eb832029d8828ff031b759d366267cfba24e35f01b45c637d7727322e60c27d55e65871362410c3a783decca9e65e821d5a21cdb8c5d97e13cc11aea383fa8f26b602e3a9d895ac042df6c2bf9d42bbfa6d11959cd9b9ea9d5202a857ae0b3c04b7097428f3291a50e86d07085e24b061972a0fafd45 +cabbe2b78d742f7d8fafcfc03d8d1c5464c5379c6a34514b255add1babd0fbb955b3280f9c9b9ee22a6139fdaccb09f1bef5f64058b9cb24aaa23b4bf88a7f34e3601ebfcd12ebd497a70c673c58b303e960be452f19b397b91e2aac835c7cc395ca2b0484272d9cea2476be8febfde504fc9cc392ae1cb89e464fa226f3eb55 +d9f356c3beb34dd9d2577d5cfc5dd9d7571cf90dfa1302ebb0bcfc194de5185237457e7324033655050e22b976a45fc5d54b5b22c0d50ac7762b6d812c5f32d682624b07e71eaf335c85205606475cf9206fef4c5a65e1c90cf4bfa74a136f592878410aa2784d0b30373067c2bb529ebd24f1c50e941137d244b83d903f586d +f2d4f9085480253f2946c7f41189ad8351cb734f6219905cb6f75537d6b505a49c350b5af52386bc59bb946ae662690fc349e18d31f70084b72d981fe557a70b2ebeebdb16a25d63dd93bfe9ac1c2a919ceb92081d7f47f5db53f9a66e5907c83201e41028544d14b1524516fdfdc1effb6741d79621ec127545ab4113d12b65 +ebdedff63552b39b84b4435c4825a88b523de9c880e30afbac8922f6a296e00ff02296fe3b66583c7848daee7b2fb7acea9144d7a5d3b7d2ca7c5e109584d08426069bf599fe097272e0dbe536caf767f0520b25ea5f678a255d3efff629aca6435a296f7cf6d29bb4c37372701c37ea7a952d483dd0d54c45ce6e7fe61e1d45 +f8932edaad8028dfdc82072d6ad44c32ef59fd388b6573848eef6239700a431e11ecffd167470a2d4d05f2e6522d69009b6883f55baac1b894039b13b98d6b5ea25bdf219c36040964551842c564b8d13ebd4b729d8156636bb7fc0a7965462b5b3c80786ec10827533be07445a6f66e54ade6155bd008f710e8dbe69cdc6365 +d143338d085ed0955e617ac2758b534a1fa75838e0f10bdf4192142c3c47180ccbcda159813a69c9f6db92a9278285315df6b65757d42a2a1555bd4ba3477dc65a9acad854a6fe0b76089ee6d7b76143fa08a67a9e98927fca7212ec94488318b291858f4fac01171bf595626dce76ef81ac84cd58602a43770a71945e41f20d +c7ff71337de97e9bcf2e125b1731a7ff3c139e4e999a9992c4d9b4893f4756d94507a366a6d8d435b5f4b8618a36cefbedecd4fb9d2c2441dc47b085b89686de53d9a1a7e673546e94db1315bc8369e3866965f55200390575a1dbc4e1e8b06d800068254a21d54c6d79bed40e25b625f6a2fe012635c1c7fee7f60e49582015 +f40213d83153dcb0b019d5ced1f4b3e944881f6638c5f325d8ed05a4c8ca5a6ce38815f336610ba4ca4c7337f15ccea090478c97f8db9231ba73af7689434fbc6ec171944dd77908cd0d329a306957079b6401f0f34738791093d71fbbe9f7af7e6945f7a0c8806abc31f6cffce47c9d539f3f4cb9fce3b0ca54d1177285f145 +efb3b6ac061fcd4bb6411ab78ee10cca7c14b5b9dbd07109d1f6e03b5ef11f4726a88f89a5e79e66a11d59e2ebd426b3f21b34e25602adddcdc87753702b1e4b852a565525559281d32a753e363a98723f365c479dc9f1dea8311d723dc016e811e0d8e918b63c3e6c3e17f4c9a765fec6c563fc1ab1ccd5c916273da3a0ba1d +d0b8a638098319ed6f0c0bc2c0e23c36b000059c0883a8fcdfe9357f4541cfa6f06d0355b0092107459a752b040722356d7f95320d7206deeee6dca587a60acc2c64d8b63067ca8ac10d221a6ae7311a083d62d180f9524cfbb7f5b3fe71f0e82bcc29b64d55872eb03b816af1d23a54d6fc4e395764d0dbdad63e494b16b5b5 +ed0752e6c489b4e37b27a1a90073f5958a7eb7dc6be8c5fbabae963784ea0993152cb9b8e0c9555fde1cda14f4e377611e66a7e7f50166a6eb0e37286a08584d931f47eb66dbb234c7e10a5080ad84edf57765b0e2c32eae6c725cd95932e94f1475a1241d1e3f8b5f11c0ad8f399332a0c1f0a54f48f81455920ce94a3d18f5 +f2164f284acd56b67aaf1b0cd0e733709c7ada139cdd348c91eeb742303f96ea21d3f4b423326ba8cd95fd1c36d5f99966e1dfb075fb13ffae9b2a37db11824a6e184980ff63322a336cbe1cedb8c748349dea7673689c4b34be89d065441eed9b010c540826a2079346eb90d80bb219c973718670ff8803afe28feab3019a0d +f9a00b6f7d7638db994b087390ba2b91cca6a3c30682898efd42f300aa20116e0bad9392294b06fee445d694bc8a5d93e4bffd7f4deef45660d39148230b955b0157bf62255e31861f9ee002e78c300a8d93c11f3d3d7bdfeefdc87231c9001fb7cd41387153dcc91f8a1a1663718494d9d6c866af82c0df6b796943ddce0f1d +d77482d83a5059204beacc0c1dea0a87347b5dc9e5dd04148a9339067121e4be8d8f3bd13a0780e6efdcc077be7f1281df3994031ce308a1bac1024144dde9e3587984dc76b919e941abe1b9e6a6c83076389e05b209966b698942f02e83861a30349797354f02d3a7d1fc0797a38e4ca94aab692e9d242f8d11d8e9ceb36e65 +f36609d7add6e2e5af768e8806280de76a92799a44ba2317d16b35d8120480ab7beb4550c706984300fce781bcfaaa7f34f4b8313ba9e350e35136e7dfe060191dffc4f60803f87a23e70e78ad4067a6ca1ceec7605ec4224d9e4056322fa932fc8d86c3eba6904028ff1391918c0628f23425369788e6f15c5237f3e945748d +f76aca3ae95e24732d780671dae23eb76e95320b999bc3087b9fd5b47ed48ac45f276df913fa29ebc0f267c5d6149f5ef3e995252ab855a75ff13294cae22463caad196c29593233bd345c470f48ec0a33855caf026b02c7e9be7585e6a2620ac8071712520903ba6ed56af7633e08de22b65c24260996b905bc7b17305b6315 +ee47144c7cc79048da2e5c7ca377d6bf54373b0235788f6515a4d05d76427797e8ee951f3880d80105a8b9a5e584a09d7a278f9927737c3cb3e65b00d166696d1e299a81d0b63b3d16c2e80ef0769ef0d49219b97d88772147bf19c8e0e2354dfe0753613ffdf82ca10b79a606969a7d10ba6ef12d41cc9ef7a0ab41a60aee05 +c7512a6fc248a703f04a4628a04c5f42925d0b3a0bbd26671ca332a46ed23a23552581ca3b14fb93c50f2b34f27a4ce81b7b32469a30a02044b08e1d8c76d48da3058e821978bce032f5f8cc59d85d30ed8f8cec79c716aaa577e1c0f61afba873d6f8709695f4bbd22241886fd684db8f7371947330c16dc5cf588393011035 +f3965870c5a0eb8f3f06393b00ff005947a4c93ca91234a60e0acd6174533882abc26e4c4660f194a8851b59029bc31ee4e696fa1fa59e7c88ea0a2b91960d4146ad140286b1f3d3727d0f67b29394d00a604e65e4240b9c93c735f665e1cfdc69cd48a2dac10a6c7b5140d8a57ad1841d99ac5631fceaaddd8d6578b4ea8ead +c108f896edb6a310f4b3acf52348f351a213a75eadbee769f484a220fee6d32fa5ef491f9d39d964015a4eb6f741abd14914cf03ef05f039b0eb0361c1dad1836dbaa575b6b9cf69d3d39c15f3fb5e1c5ec54a80e49636096ab75916e269b1a15cfc5cd374a064a3251b5d6cd6de2aa65aed83cf68d4dbe1ab9682e98bad22ed +c47513e74cbb89be9ce2f69b924430b0f84c0bf6b99414e7db74ac0db1d31100d5f06bf3310e11d1feee623c4998d40dddb72481c45eb87ef0e78b71b85aa1bc121613106dd4fc055a456dfc0a708c5c13337214aec0bff64bce84a49751451ae207b393b2299713cb705bbe69b11b3dde3f818d3fbd8293b501d027b2c2cd7d +e7c4a401decffc41ac44a48dbd92dad6142e816439b07a93c64b0b3eb772d278aac72a5583b93be6d23c85c91a22478b7ae1e9544b05747d5003809f17f89593153595cc572f9ed5815302e80c5eca2a360f030ad556787222cacad104d6c20514be1ff92047b6d194c5706c95e1c5719d25fdfa818198879d9192405b546945 +cf1924b43aa3edd753df6dbe5eb4453194ad50937d6072f449185a6f704dff7f70a28e317e0c5e8c8d67164e83df9ef57eb748b38c4a08248d56e7ec06caf4c47ef7bf09d291fe57c9b0093bbbd36c323f383170e4d1430012eadebd912ec07c507f2b91de125d7711869e7311a98f4a3e63c37cbf770fbb8f965c8d8f337135 +f8aafc8ab799051e91d03ebc27f3126b952aefbdeeec0957c60335325694fcab82a7b5ae5807699479851cc4c5c50610fceec008da4a5591a5065379db44cc33e3d8d654442cf7d8867973a5b7a967df6005192305bbbd556ceb2f51bd80115ca86fd299b9c01e51e6f7467f1dd6decda49ae2211fbc8c1764cdac271290316d +dce1b066d202d9d4ec6be321dbe4a0f27be678cbd16d30bdbf55877c70d7ef875fc895611b7c5988e1d2c5311b4885b3a8845186ac8117c17d9302b66fd1de0855058eae06c04a1d6ed84facea5d5cbb88cf5a8e7790aea33619a681858cfed59a7cb1db54f2d865c71556d4b9cdbd8539015f00e264c0bc4e4570eada2444c5 +e9b694930c95ec62abdba4da1bf14713c02cda478d380e6c4cf3e3a046fad0807211fd0c7f1f0511a28c83cdfbc56f48abe9daaf48b10433989ceb489aada52f35d23aa25b8ca027f1fcdc8457afc56b177aeb04bcab67146ebe9b2ab1e8000a8468f112c07db377bffeb6ad81084001819a8e1bf7360126e344105eaa6c22ad +f2b747825bea0eb69671e2ec7894a0445206269d9b04a1fbf7253ef4a69c05a9ed168408962ac47d852c85cf863534d3ae082e2fe90a9daeab63a37dace95513525731ec16f629465b9f7f05449722fa06c66e6c8b8a909344cf2d4036b5bcf044fd7dcbc50eb53cf2a1246bcb564f8286dbd4c6e8ca155152fdd1b1627b71c5 +e1e43a3d617669dff0cd6d191f3c92516435c17e5b3d8ecdcb57182b7c8529d7def527c14f660d63e61bf30b953f187ef06e378b2139ad0f30f4dc6193a3df84eb265f4578dde745ef8fa1f10a3b7b920bfad2a113452a222b8434d4000d53e52d8e00c3a59f9d7e4514ed175101559c636e90a1daa5d7094db4c529a0964145 +f1fdc775e8fc8246bb2da1d922e140782d2f4ffe317226701bcdd3bbe97efb8197f2a4c3b9e59d8d489eec1eef8bb2e39466a9800b5b112d6d8cd8c55eef993a6cc13a8f9fd23ff53cc12de466e24a033674cfcebe7baf90c3c3f1fc366f3c463fccc4c02dd074b1e5f83423e4e26fba1d35d6b90f22f0369e4fa35b4b46fc0d +ff0bc4dabe703216d2597fec46f08827f09d8277baecd636cb7e63c08004849a4baa21ded34362a871db6afed09e0acfc73cb36220bc5ed0489b022e1e2491eafb0f44c96bc7581ea02d841179f4079370b4dc576357723496fe7e0217dc8773fbdd09b562146613fddc8b38ebf33e283b9f3f5bd17bad87b60d34a191b9cd45 +e4d00abe3070d6233ad696bba8c4ec62f9d3b372a799303bdc4bda030d78db01cdba42919778bc3ff5703fb14798ed26c182cd29852d2488a9f72ecb2e95a7241df1f8f3372ee7990460bdab916884e47ba8ebbbd5eb010bd36b267fc0be5075dfaa772853187e02bcaa6664dc3e98cb1744a47b15e6a92352377ffd5a7b277d +dfcc6a945099cc5fc8a3c59d70e46e29acfade7843ca12f82715f5eeb8975a379afce84de3cfc32840391464413667d6c6427ce85d26fd9a737c5aebf4caa6d1419c2f52f661eaa3a05642d575f855a1650924a0b9adf410402a27f2d896907cc674c16c04c36a385b951d885608cda14a16d6905de193f7e9afaace19a26f25 +f756cf4396de4683afb81f0b1be7b72fe5304e807c430bd35dc598846a3c78a0546154c4798a43c15916f1ff06467bc4d108ea1a339f561d728c1a4e0900fb7f22da26729f5f4093ed53e44696955ff94c2211359aab0d7771a327c69ee934f31db90b4bb6c85c805abbde0feb40f6c26f9d14a496589ba1e42bf86dba5ca025 +cd3ec9b8f738386ad4b07a2411e57ecd743b145b6e865b28bb78e053be310aa7d4ec30e375ba5d2be7cc03719984c05ad512d0bd1f1e41237c1205db19f933c4c3f28135a7935b38e8bae7bcc5bb3fc8810e59a1438286b17189b6feb5dccf584b883a42c14127dcfca06e4c7a0249ff4bcd28c78b7a0b4f608de3a4fb13713d +d1c3b913cc9a0dc1c63b5da8442cb55e508a9fb81fa5538bcda09696fe73fddcdeb2b9766a60c6fe13b6b5ba25cd99414a29bcf87bea3225dcb90c9e5c05e45c982c60e36af6630d023809d0c9c68d7ec1d78088722be1dc45204a02be07f7a33f3688aa0efdd486de336a6fe9d40b24ae560ee94329995c67dc43c999eb584d +e6906f19fbe0a7b73a6602c14cb916c205e117d109800b7dd3c3c0947c65a58cb7933544b2d9fe95defc58fc514c3b7b7e661549223c407a66d8293d895ed71224dcc7c9928867c0179719421ccf1432f01481e76c79ae0c5d5b9b5c4c43d9a903df053da80aa6a2297e7727f8d263f18052bbb4691e7bc2679a4ed9b1655485 +ffaaceb134150a10384cf039e8ad64bff0d2f34e26d5f69ff0440b0d27f9964fffbdfe722279ab31e4ec029394f692dcf8701edaba8b577d0ab28e217e60e2ae885ca72b41624ea3c0793eb388e7c1d513d4c0169606a9d030cc397e8dc3cf0e59dabae23c06de3651ebe395159554f0b6b861bb22c7b0bae083936ca238f43d +e1353b6edcca52bb2e5f4856c771853d534cb7be128ad0a62fff102cc1ea0c83f143afecdc865fc72b1294a940ad4cb7a0316c255f87ba7dc848e7a6a81cf339d085d64002815434431a53c2754e59a8b9cbe97f9cb4321cd60ac9fdd828ae9ded8954efb7287dc088212f66037e5fb80de89a60a5c5daecc91c371295a2214d +e2f3e64e2b74da49aa0993acf7fbdc551d092a9bb47b9c9d5243af4bf4ca6c0e0fb7b7cb743acc4199b9829b6eb893818bd6f60c40f88095efbed69aeaa877fd59e9780d68e2ae38e5389334db71722adcb041d4bd31b009d7ea342e2964a31ce795dbb22b62a6aba4e50edd711db57d3573d96f6d40a5a0eebf5f7fc041e665 +f05bc3e8dd7a81fd90afff645e6f99124219ef8358f125b4deee68652446147c2af8a6eaa2527d9a62755f5c663b936792d052ade822b93f2aa328cedebc9fd32b787a5ac88cc439294672ef61fabb0aacb5a8a33073a6bf8665cededa4fdf80364e9a38c4f2c4a348cae5c7e29bee6c49655dc6a705c3881c7e408aa5385725 +c0d865f35d27caebe727aa38ddd5f74bfa94d6a194d92123ce6a2d939bc9208d4cb9222de08b0515bbad5ced083ff087e516d2e6c3b37755311d233c6cd1b4e7273cc800e5704ffdd28edb92b781143f1f3d259a1524a2762e4d6ec13c7918f54766e63f62305b5180d904a7a648ddf18ac448592855575a0ef5797cf47f893d +f032c386d6dfdbdfd28ac2006ace6ab1591adc464269b33f27ac5138ba399226c151e9e59894d48b0e94ef366884457baa930075b179c7bfb61cd1a452b9149e9fb18dc937df8756d55b3c8f4c2b5419cf54854d3df18df3769eb6b7f0926764952ef7f453b460941cde1b868be3ec8cd6aa333b3a8b45bfdfdadc3bdb59b3d5 +da1915e7c7e36ac52d28383cbc60036ef18185dc10eb99a72cd55b819cf5640bc3ed899ae849a9e033634c9ae84e8ee24359c2502e11ffe142748238a2e57fa08c46b43ea52742eac29564b598f32da59ae9fbcdb34fdc30d3e1fbf3b08d0076344c8eca5646bdfd787868b27fc615a93de698497580586f41cee473f9309425 +cd2946b5bc0b7e1289bb27fb6e81afbf0fef4300f5d0317445419bf9aaf4835b9e6d4c6c10ea746406e45942bd697a8147887900bb31d42e18cbf29bba283786526823540d959252f74a3a6ea9d5561f66e9ac0cadc457e46126fd3b99dee5e4252449c4121722b19bd01d7eb6811f705487ed1d4416a274798b05d5fbac5955 +ce5a745d1e79d7b335d7c88377b1c692ab802a6665bde0af07b37d70e982e0c1af32125c8af9c9cfe22e872bb4e3a71ddc49d07ee17db5bf045995f3b6f4d79da9271d51b89bb13f23592cb57ed01eba6c40949a967adb0f8e3606782e9866322f3477043ec8b65d6718bea34aa025e8f08eb0a8468050274a99bd7f05711ad5 +ff5d660485911741bf3cc5f0c060444c1c847a17c2d7b68b40b644d944310ae3a4dbe878131bc6685242ecc37912cfa7cdc6f4611f7b9873ea0e75c59cb7da908d5c1d503a1720f67bbd2a15f3b035b4e89f39383da64eff98f34bce4f3ad3a91556c39986ef56e94cb7442df4f2687fa2dc965011cf0314f9fd0a4e99f8a82d +d92d8e5d030306cbb0b4e7145a8a4e0636282a5d7f29816cc37366e95d5a9f51415539448edbc6903b07f0d81b84d5a8a33c90f7b9e4e7df1e10bffd107dec6d9362dc86513051ed064f8ff64f156903d0a96fde60811447570cecef2a77cfbb9ea1e3e43ea5d703d39fdf0e3720338f7eb201641fd0c63249d97bb34227ad75 +e046388255096cdd05bcbd3153f97722a6a7841b7c49f9c13542713b5909ec25cc2da599b1025e224b26930b5aabd4bd2e554ba3bfebd531c9586f38d317df4b6c6382b67c99bbca920e7592fdde8934cd38c07d3710be51e1ea08766709a2d63a8562a079ba6116265431cebf8cca528fd82fc77f0a2de81f6e8296fe0715b5 +f5ac18e52f951d10be9300cc6f88abb46f237d7c0bdeb4a088e9352d8fcf1dc59c5b54751bf27b2136eb9e7703d70e4287e5cbd5d07848ec3bb116d977938bfbe288d85e98b68cc1c00a15383cd01f6324f0d78b44500bbe68b27b32e19778a165352214eaa2156780deeec3274ece0ddc7f93fe11401bd49e915ccb664a3f55 +ebb41e1f5442da75e42bf4b8d1dbaec10e59b71b126a5825f03707a9608512ea068436c3afa102a4d2044ea7e6a15e70d5726d8f68f9bdc79f09abc5a2df6946088467b35085fb626a1be703441ccf627eb9b3f56e07d932e8c4b1ad3b2ff399de007cbf72017d819c4ec8ba10daeb75ee00c74bdfc11ccab597352a145c88c5 +f695a2a2b05e885de58d21acc17e7d0acec99cc82a40a0e65277cbbb12698e1101b7d0e30828a9cef39a3661e2533399a754cc67f4f927e084d0c6e756f0daa1e53f1656d637a795972a3d9e65b8e76d5a9556bbecf8243b6f5c56858a0b5187248630a6ede79b202ed70111da94a25f8e95abec93672f1650e9f94ad8e8dea5 +fb1965abe9d6b95979793175667a8174540dd9106ca08aa16da6ee91438ddb51ac0be3f88ac43b3ff3b3a8fc72ea00d669ca2424040f995a63c21fdd6806883e36bf88f7cde516afc79cd2ab91a030c9fcdf8f043cdd33e448178a37f5a5c75fa3eecdf93c24b97a75a09b07d8b6cab8d81338e1155a31305e60bc7bac49a9b5 +d08191f8d2eccdf966eea365f8eff23790b197673dfaf8727de20239e5e64acaeda10dbb9d662df04056a6d7dccb35b4eb78187ffd9b7625baaa1cfdcfa7801a19e63f5353407f5628f10f1dec5c8a02b5cd51cdaa3320ece9daa1af982899280d6942fd90388b819c3f3550974814fd336785889f966a751754054d31eca70d +cb6ae70226b42cdceeace435730d84c2e0a62021315a08f8c91746c6eb4ceb5705bc1344ca936d225d6a8adb1fd6f9ce2249a16bfffb77655d314ea4daabc1a90be9641b787847430f03f1f13b2ad301d8007749a0333ec9fbc233d7adc597331614e7789e0665676aa1eb02aa6fa1846e1570332943f304f96f4a9d467e4885 +e91ae993af41925b63076c8d6f97c71f54802d64ebaa90385676474c25c360084080594c4ec8fa2db7436a7b18b55af2c7902c4cadc0474a7fbc2e82783af9bc87eb88792a0a4241c4b99383585225f1ef1c7e46bbb32c8ed90e83cd2395688821610194e6bdb38d6fbf53870ac9c20df991227c598b300eb7955f7a44d6abdd +c865501f45da50c7061abf8421dae04745125764a6fbad33fef595783dd8676bad62c7ef7853e4b75f4b5aab8bab93b43999a425a83f7176199aada5347567b70d514d2c984bab627c8a3db82f29a0ce1f7d70c1b0de249689c7c59e279ab94c5dbe149125f79196660813b7ebcce27044e8429afd6be018c70a49cce6d76d9d +dd8abe13a5ea14ffd8ff45ab9a3a35b90e6bc79c018fd1a1005cfb7c721601ece24f2078b2289a6afd9bc3d2c63a7e5c7623051bc4ddc8bd9aabc48b7b5d2b5ca86fbfa6b8c980b37e7d46bab3734887543934bdb0a75eff82bf238999a51cc1ad0595805dc27068f8d23af344e022a916bd2012fc7038f547f92d97f76112c5 +ec32ef777c9318c52ea24f7dbd1f323cdfbc1fc91f8ef39248190d4944d320ac758fffcd5a7ac3df78761b1a27cc90da44882672496ded73f2998e4884a86ec264a2f368a6adcc210bb28a9ff66358f15c5e531044a71a7515e7c17d00758b289ab786acf07860e0de22deb357fd45d2f1bc289277456cd028da8cac1f0252e5 +e1e11019dfb7beb92187a908847bfa04cc987466e9f709f3fca57d32699d961cd6630a147ddfa228c30e5c5b6e75d9badf16bcc6edb5284edb255c64c6af7f977c4ccc5893a10b621c98a77eef18882a25852b4667dc6cb03a09a2dda391fff31548f4abaa33ea5903ac891d907fd2e2f56706ffe4bf6eee1e01cefe431e956d +fa197e6f7fda770e2db0630a8d13e4ff7154557470fab3723ef0c7af17974bbeabfa5fd67234c92790f3806e65cc938925aea2eaf11a27535053781166b8c5e9b8edb8071eb0dc434a49bd78b4d36557421f0778c122716598ae748051d2496c518c3fe07fa70731bb34186e6c26c1fbf3f927cfe3a6338386aae4f109df3ced +ee1d856fb6c508481be35e01355c6c32f4fd918834444c48f7dde2b60216389ccf46a42e5961cc40e6cda7b5ba2235669c466d6f14950055c84b339ca92693243b9b7e02a3c105cd6a25ac002d3c6182e90661a913ced8678c231e4105163118c2e719c5d5fd8665981d7c842c282944b81bd482cd9c4f1879442994c62d38ed +cd1e3cd21cb756d928c0f53688aac4c03ff7e71ef20dcd4798159fd8af9a105e5424a23c800a70de73cb5b22ba328dd799c85ddbd20c62bcb4b028ee1476dccc6eb26b932c12dd584f8fb6d70f4046a001e72161db28e2fc76cd5317edb4b35f7c878637b7a2f1788395fd5c019a0033c7c9caaeab1700d89deff335f5f65dcd +c6c7888d3182c721e7989d341dffd18da609b2578e48825acf5d541e54475631b5de037f8323981a7d6ed462c6add59fdc2bf323c9d1c502afd881d817b6a9acc6682cd5d1eb0f7d7cc607580703e3bafdedef36b7af7afedad4262cec7a345748b237804f6012f860dd71a25340d5674d1e599a4dd41b990f7d504195f7b0ed +da9a9b87449827f325fcb2c03bb69a87074b2b97434e03efffa97e3198e3e720d806fd0f5767c29340fd2b8d8a7b2a1df39327de79d848d600b78cc4be447c6110cb060281b891b6811ee411a92ac23b1b19b224669ca3512f85b6e69aca9405ebaf5fcda241ca7ffbf7cc1dd8984a2670b696d5d15aa3846d919552208f889d +d2fad86c78c301373441fb2ca6b8dbe2bd3088ae6f9351df1659f2a7491a203aba7ae0cd4c7c9747cffdba58b901680df5eba4a2dc9311f25fd1b48f4464b55b239e5f6fd26bed5a636b73ffb1df7fb7160d065492c6f2f8db8682aaff9d4b5e9969f0817bcd123be3bf3a2e1de81cee2b0fd7bcddc7fe6c652e6e7e9e3ce07d +fdafb1e55ea0bc6bb0bacc5cf0c617b39f41ad7a2c7f760b26e963b03b1cff39a7a00ece74c36d6a964919430b0cd5f2f84c86595fb34f6c3be57ac13a985083f312d61784d966f82c28a68f4f810c2c7b27d492355f88cd9b47baed0bf6fddf5009ce95576c7b6d8a718de2444b7263ac4a1bb627fe66fa797ab27aebc9121d +ce606360ad461a06a31c1995ab7d67944dec0459c06c95b0f736020864d80511bc41e62f6e58274a3a1f11d372e0f39aa23141979028173f1778eb015c84ac3a9ba7aa492bd589b16a2fcd50288d5e34609aa84a0796fc6165a0684e7f12acd722be221b226a83c9565c54eb1df3dac8d987df544fc177b9981e617e3c160d0d +e0f7089df05ba237db3b1c45bc21d66c29ccb507e9daf95001c416827fbb671390c97df7b83788e2569a5c5fbfb6843cc695f239f5a1e95303dc43eb5b6af0f1c68ab9e90bcfd516e6d6b6ee40d4f9ba37b6c048525c80283488d70250c5cf99c971e66bfecf91de978dbfcb7c6ae04cb05ef016202f30860479ec1f90ad4d65 +e8507ab662b3c98ce61e0a121f721a55fd03f7ae5112227da37af43bffc91cd1467276191a561cbaba0e34c1f454f679f3999d41e3670135b1830cf637397c4a5da44e050f872e2f9ddf38796a72fce90591b01f2e2c5fe715617386044a8a971411027d3806d6a095581689065bee15a4fca04958fb5ddae0ebf5a300300b15 +ca0a12b96ffae3b5527115329f674292820ce3d4088c63224afd871f8119479a55dab101651ff8a18c3adf9c72636fe333c4b3ebe674efde597ff92af502146127990e7cf6edd2d26092c39a5c54bae54cbaf1bffc2a4694b50c1d85e5a2f787d5f9440626b3106ebb2e05bde7a68c2898285f37ee3a28e2e1c9b0d3a0c485d5 +e3e88bd18aaf97c07ef653e8fc0a34c84fd1253a3569bbd446dff4824c2603c7f8eb27875c696cbf4468ddbe68f05441ba1ef367a318e65dcbc1933e89386b188e530ecce528eaec744f90bfa84646c9ea20bfed636b3064b3af93c55e78c984e3bb6fc651bfed438ab861acc7122055624ebd4498833c744b33ffef8c00e1dd +f8456e31f6500650a486eb37443fc7952d67a1769c9fe245af454f76ea0b3c5e7a16977abd85af7d224430556114337e54c2edbe2b3c168b6d091ab6969f75eaf010eae3967f346cfef4fe37bdde5b945fa81c545bc60a44ca4cdb881cb1d85d7756f3106c868ef2554bad9fdf621b6ad576dc6502d3d8eb338a6c661e0b4575 +dbd011e8510af2bd21a8e5aebaf1081feb39a43579a91b1287d1855ca69b461bfb39ff789bf9e18d521a29f9c0a98f801022dfe2b48ab47211d1e2eac93507553f05bcf830b9c0cc01a82e23ac09ded672c36287ec331146d15837a5132464cfd9a9850198ef18685376343822e6bd00b0042b0fb9a10c87e2e6ea25ec08574d +c88a0d8e14d4aa0b128e0c7b39ee774e520293f1dab004456f11eb20c812d76568b4255db7f62a4d003bf2cfb2e1e7d5307fdd19a37045aba83e3903cc80783a40c5b1ef779fdbabcc4b317ebe478f89bc5097d4bff5181ce8ab1485f65ed28b740ab329b4b40f3503778531f64608798271f5b7449971aa01082b742ae821c5 +f027a59ef13a773a37c37ebed7c1f185e170ff69456875c8dc725b7294883480d264d53467a7a39a69aeea0096c69f7e13a48be0e18acf2d771937bf856e63e584dac3a764bbe19db2f72f17c15f24d32c069c3103b85bde4c3addf09b97d195c26ca32f1d0db60d1bb3e8ca124bc68cd4b347950b3572f794dcf2ed28827a05 +d0005617806e66cdf95899ad4657a55406d11afc7e9509e6c203f1fb0c1cab50cba705185bdab4f711f9aa6e357f91b20dcc908cbe10180167428ae569a9aca1ea17c66aae42e99076dd72f18eebec4071c1873f323cf6fff816845c25725c19d59a5248d680f85e487ffb0b50400853cf228fd8c5ca39888cc5791cedc9ad25 +d54b2a1f600724faeef022a75a803724389d6c3bfecc6263b54c53705d78e0344e0c6a9fb7d29f707c068adec28c17723225f0fba495f6ecd6b6a379c3472665beaa8152cf3ee69b619428f5e38c874bc9b648a5c00b844288a46c4996108d3ebf3c1f43b8cb327d04a59ea5c108e76117c487a9b82f93cf928738bce6570655 +c8284c1ab062a0d0ff59bcb818c10920ee12ecfc4c628791d690bd5aaa84a9cc172db8a77a6139640968953b11462225d2c980826a017fb1260569859a2938e2df25f5afbd789e8c2edf0acc71e5cb2cf082afdbc5b4a1f8262df03fac03a2b05f67ab51acf7fcbd9e48d07fe439dc14b0d082d44b0b761d76bfb17a7bb9b785 +ebdb28743e4d9393c2dccf2402595e183fc6888fda052ffd2cd7b6198f09be48f1377712f042a63eb1cfedd9580099ca32d4a61d32b5945557ef67d9950d195009a4195167338243c83cf66bb24086655741fa93c99d3ab51b36ad100e02299926a272d56ea1a1e9e3a5b6ffd8e8a64abf5416fb09d409193319abe153409d8d +d65eb3f296ca96032658f0770215e613015268edbf6c29a95809f565029fbf9bc198cd69d0cadfaaea3105914a0fb42e909108417b0c429eebd2dab7833a3a840dd477de79e8e0a293fbb0a852522075dc5136e6c11cbfb0b17d55c0a7efc5bfc72e4b4b388eec6aaa0d0faee88dfd94d5d894f1835646470eff1814bbf139e5 +c05e541401f5c14ebf63bd8b9d8fa9634438e7fb90abd491f818d98000e0ffbd3452f77ebc328e2be0449f41d2c6c5bdde140ff58dfd1574e9720395d703fe10ab0cab8bf3d3ee0bf1f733dc5fd34e0da04ca61dbb977a83e27f09b23686daa5f094adfb78651907dfbd1ce6a6f18c54d1556292e1f7f3e94d76147a89fc0f2d +ee4cdd912fa1bfbb9665235f0a06a7cba1a8419cdd12f8a994adb73f241e5bade29f12a1a1e4e81e5d3beb88a15ac2f38e8f55361355a777706812db82c73b6f332703a9f5a4fab39a3de4160b5db08ec30b7047b88091ed3c94140cb753eeff87303ecac29edd3ef2332a546c0b871cd1ded23f27b33852d5bc05fed9c34855 +e1064d22e161db40a96faa22fe4ba463b16a94d17307cdfce9d9c0b642c5d167f1caf1dd777d8623f8dd0a1e0beded6bd5944a0107b045cc4310e6550db18703179d67377af2736ae9ef32b8e625a31254213d2fb63c815a960f78c18cb678ef77aefc1dd3bec2a7bd3d2e976a76fa7a8a6514d1e5d18e55f3dfc09b9aed64ed +f6bf2537599214db59122973bfcec0e66a65341e7bd9fc04c24c9600956b6fc07477d954d1bca1c854469182c9b31e92f7d78179048cd423ffce6f9cbcc91a38b4af16ea03a8d15d2ff8e3412dd9427f9954ea20fbfdf1fcae506d5d732b14a2e0bee1d0f93668e71cd30ee6da165e77dc8935353063de550c8d72573b66f635 +cd6dfb24defa5b2b18cdef0eda2adf0e861869c77a9ef643e27d9d7a02f001e32fe9927c1068aa0b2ee6de142623b161158a02af1c5d49619453d69556bb8e4dbeb36aefd74cdfbe384924e4afff623e4f5ea764c41d65f2032ea5c15cbedf0beb93f852ad2181b4ba545ca1d87fa9d9fbc84d37ae6cc0270e38fabd4ad160bd +fec9e49cce336962d2617746705dfcdc39ddecc68edc64fd17ce44640aed8577882d1bacdcbd504647ecf987095d0a3dc4f5b8290141ac0ab7442b4bdfb78e80f3540a0b85946bf8496a0ad4bf0d204c3236524e6cc09ca68f23a341b31ae7bad457846b0a8c37d4b9e09f21c1db009dbafae366ac179b4d5885ba3f3486515d +f4cf8eb9f784a44c2acb080ad31a8cc9cbc2896ea56bdfee5796eb213b1c5c06538ae73f6b8f3542fcd35a890a247b4332d99a8d58ccc39c3d663cecf6b29cef3afbffbc58eccc3719e9413ae52631be34af052e851f28e5fba511e0c4dab5261e5efdeaf4c4de17c4cf2531963581e038c878b677a365300a377cc8a36c6e65 +c5aed2f3eaaa7996b9b4d936d94d5e73fe64bdaec3a3b2d569a59c030929d43ba23454e922c76bf3e122a0798f6120f87f35a5557ab785dc2afcec66fcae2bf2972872613b493c5b9628d6151ca970b6f8185025eb4d253be4b638d17600b5aee7661afa0e6f56dead3d2de75c6d4aa0c0e0bda945620b44df8cb41f05370ec5 +c101c7e5ac5a0c57db703d288230e7283bd8c9d46576411b6df847260851335e155e08770d9ef9c2ac27cd575860cb65fe85eaa89eabcecc69c0deb244b7fa824cb09763d151a23135bec7a26fde2107af92b10bd1994c65dd25ed9b433c382443987af8edb72527e1fcff85bc0a94ce6de34549ce57b2c74321ba3975a1c0fd +c8462781628fd6bb2c9f47406393ffdb3de02027d4bc6a4eb28ac3cb21140958cde30e5a6201ddfbb8a1f1d40789f439b295f46fe034e077969f895178324b9f23432053f19c0de921076739c9115b364f2c1ad3267b3281814d99b769b386b60f14a57dd47b4095e56b6f0e838467be9e42d208f5574f231acae151c2ff0cb5 +f37aa90dd2a3793e0089a89a0d26e05c38a73328a39e21bd94512b1d81a3804f180f98080230082cf34eac7a602d78c9e402e77a05eddfc6eae2a8ef68b219d93c21feff16e50cb51376ffdaa51b9a930a9b18528176db4ec0c0fc2a535a0eb2f82eb5a0c5b8928f199458796ca0d7b2541a275895c26048dee1f7ea89d61d15 +e47f1e715bd6328113e2353bfc797cb1a008bc12910747730ba17e7e3978763485a68d8a6ff3d116c89cf81bfbfb00bb8517d382f841089a688d33bfeb8ac83d6269ede3d04f831cd65fc9e176c5295b488cf4571e1269a33dc41b1f079b7c0c5981733d878a5785fb261779f529d09d6ce90e94988ac4e4308aa25734ba08ad +f3b54bb99708acbd6ad66450e54026cf28a3c958eb019bc18f429ce68c06afbd52f63f9769e5897718564aaff8e4771524badcfce709a67c6350b178f436f48bd5dd546f3de5d9cd2b68e0c9ede5e9f474703d1956e7d95af0c8bb8d75568b200acf5f6717193ae70c7646676481af3dc2be3c777e1932915f7d5614d0af1e45 +cc59d09c80ee1962acdbaa0443945b0120ea91d7b95ef6ed0d325df83a8c8efe9b022ca8670af6fca2e9f2f0d0454e6b5430a8233709b2a4611163ea979f14634341446b8be00f4dc7b1b6920db2cfbeb1a75861f3d38b373b03a35ec8270bafec241f226dec940003b52e47489835e46a79360c963363aa862e5a316cbe3bb5 +de3f7519b2e3a2538cd66e3b2ba8f5ee8e67961e89a5560f1e89a8576f425dd8c89ad8a74ff176d76483b75b91ecbde59764e9d477d051374e9276e8bf16e132b66b5f33ad93bdba3d3ce14957db94482bc0a1035be41ebed25002e0df2dea3ba33f0127be27eba5c425d1388f81a6b9d52f7393e51abb202a04a118fc9d6685 +fc107d5a74aae7288ceea89bc44c366784a36461f2af8005d1ff880089fd7190f5986de041a583341d8ff7aefa3da09bd36ed24c2ffecf1d0951ee1b34ebe1cf737e4836daa7a59fee6033372eade4c8b80540e6b3c6c0fd4606f6167fd9d355f6bf650990f5fb64b27b74fec2beb1e0d902c536e08d199dd47734f5b7843935 +e541479fa9d88a4bd4ca0f6b7f1f06c799a8c1e0eeb441ac7b8439f08fa1c6a947bdffa3e31c54ce678bb5ecffd40576fba60e365bcca77d479f9169ab9f2f1ccc8468d53bc7ef6f2a4b533e8c3c73e3ecccb686dcbacd448932f3f7fb68a2505aefea662f4b87f259afe07bca12cf37de5b0103b7df99c5bf85fcd72e2dbccd +da26fb8b8d311836ffd5db5064ab3390a02ec5d4f08b92f18dec3d14a458decf147268a65b5cf85cb809e30e6a69b032c3ed89cd6703d4a7523ffb5c7863762556ac0d23ef72d41b5fc3c701b603771d859712d20bf486808158b76e3c647f9919f2253093ee441d9be8f638c38ada2c7f5e28530141d8bb0fdf2192a023f0dd +e57694952565c980f833b0448ef58ec973a1a6e9f2b497bf0660785ec578ecf9d3011ac2b390639c74ba8ca9ebbef87963ee133babce7aef70d27715620572f857413e02701a1070b63868b483c6ebcf419d66e3aa41fba5c4b2130dbebb8977e20489a485ec415ebbac10b169c0b0f1d0c21a96c52c3a9cbc71ed008126b165 +d6247d1a9e2c712a162f0d894c7079d3a8beb96e25c62866b467164d1172e99b15b583ef5c26af9fccb964d15cc778e5bfeec1ed3e5713aa3c09ac3ab353ad6c57b91705f910e8e0efc2d68cf81d7d604853399f811ffedfc6da6030137b156dcddc026eea0af1f88602072a4c0f119717ad6fa98bcb6b78a31e89e6f2dff105 +c19831e7cffce0a3b135f9fe75c84df6accf140118c762dc8d7d24bbbd58d61b93f9e41d49581e7b27b1322d16cab0ad0f7ab9f6d4885a1d9532e9126e1a4a2c7316388549ad1084335054a19bd1cdf2e7828d529c2fe1fc4d764b31ac490f26047a1564aa419dd99c9144095e35650b47934f29fb49343702838630fd9b2605 +ca44e81c9b8fb87c9da389778ecc62b97f40d4f4a5a0a1c6644e7aafd454eec28d58e5674b03d4135c21feca01a3760d11bb919b63cb6721c94e99cb6b56de6e0a649589b88bb229847006ed55a18b344a4de9b175a2ba3739220e6c107662920307af9e1022c7335a0955ea358df0ada2ad3943680ba2e0852d6e3fc2264b25 +e0ebda026946f37448a80a6d6cddfebc8520f7336c499b18ae59daa4b9122f6591e19f47a8603b4efbda0c07b60f6aef095b4143394fe0055290ed3d3ee10bc224d0df624a735f08e1562efc8cc338d83cbe95d372898c0985e947d1d61a0fdad9ad8ced32ecc8de121e3c52033b6c606540e996241a981387f066209d8951e5 +c429ea9d461c269b00c787861ed26644469f9384884b028063f9b556d9ab8033f12e3df5e2ff8dc0206a2ed4060a9782b1124c7886227d49688bb433a3f7c050130aeae8c0cdde9b6d9cdb3b0d355382039241518bf44bc5320d0be029af33298ddfe35caa2cad8ca4c3938428561a33d67453d3d48d55964bc89ec16019d5d5 +fcc2f150a65b58649c0e7986e99703ba3ded0a3bf24c3a514388580a1c992b141fd974948aaed36ddfdbaacaa97890c55f5edb67cdd0e5c24a0af84d07602143fbdfcb751e6bc881b4899682c0b45ebb668ba9b86c8100fc1a4420190b51e832c42ef628be065efd668b93058d3c50f4187884f49714c99b9b81011165ea64fd +defd2f3aa104b433c09ac4e959331cc538e6857aac1b1d34abc204712d0a3e081eb43219f24c5ef2ac7991377497231fc35a504fd18bf370bff33f9518b1f6ebcf7ba527ddec3c27931a2534311b5af43b615369b2436f157ec9c4924a74388102d7d702efedce8a9e1513731c2eb4a498dd38ef3d48c2671bf0556febd61105 +d24cd7fc935c6649cc1c4016e9b434f99f8adcedcfb14c10d19460559b79604504ae630eba090a8e12dce804a98754dfe97d418f69faef31b36c9b84494a52799fd6f6554bbf00bf09c6ceb31d80c9e898585ba514db0da2d5406242ac6425da82f54b59116ad5a8667bbd36359ef615124aaf49eb013b12c8e73c95ef1754e5 +d8454d83397aeb2f95c2ef3f631b09aab13bee7e2ea80a60b23f9b62a16661ce173a4adfe7cd6add3574eaaa2e3fde776fae2512f896102efda5a5d7963b0cb0d24c64cad43df1a404fb45124985fd979ea12e3b8e04986dc79424aad069912399f9967819336ffddfcf59256d81c31287bc0f826259d7ae518f5b4c90bca635 +e5294125e579b5344bac95b5bacfad8a53033192761a264dbcb51cea719e9c25ca5777d647ae22590a3845bd525e431752718570492bb6a7aea199976a5d5f88389289ff8fa3353e1c28ca733bf509982a478433f0690a564ffb77abd035f3cb0e3c2dd9cfa27d0213bc9a564cd40421bd8553c08d9cdd2c798affe3ca61fa05 +d51665034d9ecae075b5608ca2418916d2ec4005282a8324e438aa40df2c4fbe78d339c45293945203845d3ddd9b5f1829c4b7c9f06932279015db0426e12074fe6922892d1accc23322bc6c559b6238ab81318e19f2b09f8743c84b95a873fe6e8aba102ece14ba72ec41336de899675a01bd97803e9dab17e8f5a039b5e8dd +f186114528ec964fa924e4d9ab4a8968543c4edce6b5804d36379c8598cf0cc805034bf8f9d56263998506670eea8719bb510d5ae42b56906cbbbdae35c1144052c937d208e88d4604ee9649efcc4a6bab36e5610f3dd430838947d2c45147098ca1700c642769e7259025793028677068e41afb9ce631593b93bd17ca7a8575 +f16e8d1a0917b9df4114fac8cf2793b05359e131206f02ac1ff291ba5528232ae94b0f6043184b6adc09628251e0ec605e68a9c1e1ed0f777496fc8903fafbc624206a7de1c8ad6faab3baa383e7baf8200d55a5af19ec1344410857f3c8ac8d2f3ead5c582215344e23dbeeb91c862fd3f2f2483eda9edc4f170175f6e95b1d +c338871392900e2f76e013b9f1da842dc7e7631f8198033fddd6e8eb8badf74b402e5deaf65d397e8adde339503a42b7c7e0f8ecff0e09dbc8d29c58650dd694004576ed197da2838536e3b4343d3ca0cd3b762ffb994343e546c9108cf4f143c602749daa477d46d2d55d3a34d666b0f4fb423c2d485615177fa71329bf22c5 +efb3426bb8d11a7e6fa89fe0cd868e1a58743794ddc94b08e8b187efd3a22080bdc0cde343724416e6a2200be91c1f020c2256aef6d66f661c87958c366574c0778aa225160bf2e5bb4297a3d9a22ebe313532b04fa2240f93568a07b1864632326bbf5bc9032709b9b219fe8ea3922fe113a2b772d9fb033a5163c9fd95c6f5 +ea0dd3767681178a62cf5d7503bcf8079b6498453c06fd462dcea80c475c400b6072887616efdd6892efc06503c78dbc0f1e77bfa67f34f3ccee38c1843423fc5f3be216fbf950a631d90191f9cd3a7fb8d0af712c48534a3651ac75b482e1e5f9b27c9125f08a30480d72a3a275b039c6cda359798d2e75fcab0dabc7378d55 +e7e12f4fac98c66c07c1e5bf04c07154e5f5718c51231e0d551a2995f207cb71ace535541d09024dfc68faa213cc95bc0a1b07bcf1101c623560a1f4ad1ec3722b746f202537267c69641d91500880b9ad9f44d07c991405a1d2fe51f5810d7ee081d4113e14654efdcdfcb5857830448b1af7dddac073c4728c798cf393b315 +ca0a6fc6aeb2c9b9d4298060834ddf9c91f3b4f5287a3dab4d6795955fcda75753baae06d7e73eff76a3a0372b90259d6f805e2a2c3aa6a368e08e8100acb1dc2aaa5126bc91ae8e3f15b8cd638fac50f772832b585b71adc258caa8c496ec6adea9b7b7a0ba2c39dd02df58d83ac79bb0dc80367c818948f056d655aff4bc8d +deb89fecf1aedaddcf0d635550756c7570c088063eb88c84fa9e4e5b5da2c7d2f76fea3959f771cdc05a8e1066267ad88dc348b69d6df1cdccd9538ed5049f63a58d8bfe3e28fbb0978f9aa1a300a4bbe9d07cb83f661b2d5fb2b3eb7be01eed03be859ea4eb5cce32d1fa3919966e1e56d388a9b860a446c4a5810aca2e2075 +fcf39e5ba24ad54f27b50091da98de1bd4799c605431a715acefd96fb8bf1513cfde5f593f22686274fcdaafdbbd97c08f02a8d76064fc3af31041459747de9ef4ca9ce18dc252dc8d61ada1350100ecb0b1f97d769ca8bf5b937d0383e930a4c24b68b7a1742472732efcf927b37245e82fd08162c25178d477b515d997b915 +d790dce9372e7ea1d2caee36f69e987301a1a7b1e52bb53f091a2961af1c324155d5f4be1df673285bef975c141e583cbc91f0404c2fd1d005b00ac8b08c5492b1ccea8976dfd1c571471b50c521869a85263989f9857ccfed16022ff08573c672fd29f37be59dd27e872ef5747f87b0a641bb6a8ab487adc41b900396090d35 +ef8f422500d4490352508c3e9435ae2bf8372edec93d6a850c0ecb2f23996556d3635b4e0bc13544481773cf1ddc2663c36c7b4d340a2fbb3356597eb60765f876f8c002ddedf606cb86756c16db077a5fff5646b117d21e83facfb7bad9366e2532051837a3ae753fe0d494c34835518a8c247ee2d2079259b72c2859b4e4d5 +d429f267e30c0de6826ce7f65f90ea8033c03ecfb5dd9b4b90ca47495ab5bb2752b681b4ffbacd304ecee282c922ccb042a41b462723275ac300c8b0ab2a8bd83c114b4f516497c662e8193a8bf54782998236538f41c0f5e6ab06182aec139a7494e1827c3b78d7bebcb07962bb8d1569ea0873c9c6318d3d1cc2c422b5a935 +eafe2313b84fb9e62849079d30c7574f14bc26f1b8fdd3f3d65a81508bc7b6a08a1d568c1f25246544b939f122b1cd0f87692f0c944774aaa8956cb3df84882f5c38eace27bf1c6a3eeb4ac172c9d226d540e7a77fa24cbe6c4c4c79e38d23038b0d517a17b4262905845c185ccadfc2f642752cd15bc48a4ece8eb5ef080d2d +f470db3a4ab8db8f77a9dee199005f9e8223821083326eb8e9aa412669d10c7e018159e8fd5ababa671c0c3403d7e381ad7786275a17e1ebf478c75f5e945b07d59eb7959e253731b3266dec6193a2240ecdefd82ba1af59829ad0b875724e87a9f166918bedfbfb60e6fbc871c4bf5dd0dba6c3c9d46b7d199569c85b14bb85 +c71f44dadd29e0dea2f5ff3fefc4dab4fe6fff677c82058da2321f5935b35fd5a241ba8760cff8c910732e798f5c1a2a7bfb728412daee252c20f764c818c7d4c07c971f4a60f0c1ba922dbccb419ae96c15e13bd99526a947783b68ac247532087709a6b5c42e58a6f1493b5f418d5d41b0163441cd6d4224cc762767b76c85 +c4c55b788b5ad843666d57cd124ce4c9d3b0ab6f4074fff4bf2f77a293f35693457309f86e6cd9a3351609672a5b7b839ebd4354d565a44911cdca108b95d5f4d51ee45bc5a2facc0579424264ed19365de0a50915fd5f4a8bd8b8cea7df39226f10838e84f39383927b5385c4317016f4946f7ba1c1aea81d86431caf3edb4d +f8b46dd21201e8903bbc4c4fe61b97aa663c3002aeb8434a6fee34b462a781fc99f0a483cbe9d0f20bffded09611706e81e8c2c7070a58c31acf85a65830d9b6b51bf0e807aca1d291143c26b35be69db73ed5589ef2be4d483f97197a5b8ec3131bdef4675ef7be3aee533ba6bc1330cc6d2fcef3dcaba336dfae59a4e1f725 +f03b62129d41a09715c112d11c49642309f96a429af38086aeadf7c9e8d53bf487f48ae8cda37ea64f62132467f4a0ad6cfcfc6ada4f89d4c48f76d5f3f283bfc2076bfc7f757d94bfb152bf06a336f98a4ea411af5aa068dbf8e6ca2ee9d80ba2e48fe71bbe6ae886d3bcdcdfbfd73653ce43f963435181a9cc79e0b27a02e5 +d861169853e13e90282dfdccb3d9aaeb10c2c4e996ba1893937e2aa701a56cc27ae905aa733759f008aa1c0b67f6f2a01ba176ea222b7d496a5769250c343c3e7fd0489b683684efb061f35caca1725e01ecbb4b4d3b1d83320007fc66cbf040ea0a6aca3c5f2a88f35941ba7724c72903597aa621e97d7e09c8965403e1bec5 +d9acf96b15169b736c44d9a12d7e987e2c2e2982f2aaf5a446cb063e5d911b1ae053ff07913ed7c521d30e1f07534d223c8bd2b50344396e839c9479adbd23c196f01c166d7eb2906154b3584ffd365bab7164c193a5691a5047563357026f2b404e17beba02b1b000d9e66562714413ac53d12c84969e89f014175ba27d8d25 +f7b94f600362ca592424d0476ec8b022bab10653d3602273e3ea8ac58325db414f451b82c9722803ef553d0de850c1b8c230accfc51d1b759113e2bdf16d16e8e97b46a25980015dfdb90918dc3f3bd36fbb68b7954edf991bce1c291a564259cf642531175b52be6036fb8e962dc3d8435ee4d0baedfe8451355b3164a3391d +ca0ee7ed1ca5bf9222afed87fcb7c71ce8e73addaab1d3d8b6a22f00d0f4ede8b3f3132210995fa34fd85548740079313837fe8eb8f2fddc65f9de71031af83eb1aa6d8bdccc63a07c932b8c0b1d447bb4278be412e68da81b32ab8c38a9c4d8183fd89c16be206ce26c464065166c3560c27b931fb321ac06322909b5f370c5 +c3e5321f70946d1e3165628be877b8b281555e2911dcd721546811d082ebf023c7a745a119a40047e10715b5214129e9d29fcb2d7743331fcd43b6583696e58cd388892131fce98ec1c5b470492b37ce923a74e27994b147e5ee42ae3827165a4e7e532d2b99d9d24c35af491b49665b89e4ca5039ff9d0e71288b4b8d40bfdd +d3c922f7e1e70137012dd1489d3c76e8d35a4a71a052ecd459a7df03403afd9a530e0b7f23bc500abda5a4ea51016626c17f410d85cc4ac798d1a264c94105b736b7b0c8b5503ec701ed80af25a8b2c341e861f8d0ff8f0a13fd01f0333a80e57e0ed6473edfb0a51b67cdbddcc6a28808b371add5151c5d5ce45426e0f6b5cd +fec3c5a877fccbedab3019571ca33cb89c2a2f15f7188b18e3833da5c015527f01e54d2306086ace38b05e2fd9e5bd8bd4a669850f86853719c05715e885ed8b07d01661e0ef7e59d16119542cf6fcf052d609b81b85a60ec50933251d83aacf39f268e4c3793a467674708068d24267678b550645229efdc6cd54acd7e2c14d +fc22a6303f3e5c1ff1c907aa267144458f742b0c2877cc0ac406826c4cc68fe13758b928f93b1dfb2af2f6d7f72ef79aee62f5976ff3fb36478f5958956463417e74e6d29dd438c1f5f6e20d22a046a662d442ddf89c45ca850ac31e4d90f1b4148ba7e9f509b95bb7b2127f50ee3ae67a637de417cbaad674d9c9ab960d654d +c5e7d7d8bd4eee2149c6c8f40ba59f1cc8231f7ba294e6d5b7b4b23ff8a824cb1d806eadb5d3be8444289b12a4e1622499db5bdc7ce400e60aa21c7c8180caa399b036e388e1b777a272174604714c5944fca044d6085665eefe70ee6bf2cc00c9b388f1cb96983bd3bef01474714c89b24cacbf91a8ffb05b1ae9c4a4188bc5 +d948d43d26093a2ba551b0b2e23666c807e127b9dfbc43544e28d7eb650f537f66f7c0818564c960ad708ec73b7b9bc5bb698f1923a76e16d1694e9ebb4c9bd7930a951feb570fc9ae1ee7c6da44661e3d42d6e61bffdc063db904c70c23f91d690f91a80678996dad357e934ac2d6a7d6465b2f2cb1b426a9f49c58da5527ed +c05c527b0d5fa435fbaeec6762d909b72b29a5a9e78d723e01a27d3e279a69900a4befaf68f5faa93e1ada0807c692090bef24ebb7fa5592e6a6f914d16e928dd319559947609b39857f31e72ddd5d60fee1b05dfe8ba63ca3964bca4f5a4b713ff38117be91e0c99662de63068322e462f6e5c26728edfd1f2ad6fc9b0e7bf5 +cf63801c085a59629b4cc9ff4a84e8c591b78637935e74f2a0153b168af7319393080d5628a9f42e3d7e2c3f81abdbdf0e47c0803144323e40b67fafaf580c44a56361e140d9f2d7dd5101e733b6225dee687cd695899d1f66d5bf6aea44942e31050de4d15c1e575f9704a5e583cd9ff6bc255a1775a5c1fe2929edafacf265 +ee662270fbeeff37339f9531cb3cf368439d8965d87eb53a6db314e5326bcc25a8380ff08900df663bd18d9f955d05743d7b3689120df9bff9e2cf5d2576e5f8755e30daaab8f923d9f7d623342469d84e649c47596d4b58d10022c0d2fe06f1dd27708dddd8d8375e32f8f147e293832ee60528eb4e7b3dd57a715f9327ab7d +ce0a029939cda5b28090cd0a778c5542a424f9c82daa501da76aff59fa8ba8ec2c160dcf87e0a553b29ee948c66da6979d1ecbc7b37c91a89860bcbc543d46587c5b1b992e490d9c2d813d0983e93e396baa79dd4105960c30a75ad3492b873320cb4b3442e8d6355491388b6d59153b4da754a6725065607e6126dfdca4e27d +f2e87e164154e1daf3e72ec783ca1f8a5df3354fcb358ae29a4166ef64129764ad1aa1f33fcd59a3c86bcaab4b5f5b38395761539995a03fbeb491ed66cfaa68876b8ec1a0a079a127e14f82d866eee6f9a8077700c74855044f95a4ba1ee7c2021c7a642c1a2e734f8dd6af7fa47445b8c68a7730976be70388b737b7e374dd +f968866268344e69654fc79a607be13aa6407de096255f75476165aa384c674f795fa02a5ef8f19304025015baef3a7ee33513dc9912d512df4f7beb23140c011ed78a0acd2338c6ccd0eb1db4c1d33d165a168755c55f58462ba874d436d96e841eb0a5d00a5fa230db14462f03749a45a38ecaa9c26caee2965b3b2927aebd +e783c7deda612f1caefa7b7064bf23a0da09d2ae09d76d3841171b772dc8968ba9e53ad2c2887999268cf9760afb9233f8b9037063106453adaa744ffe6fb9509cdae6a1bc15f4f771b6c602d68d1a28be70c8a160d58b9d289d8347c5616936b63c866e7e5d6bf2b0143e0b6581ed2e2b0e564c7ae20425fcb18e4ae46665a5 +d978ffc21493198cfe598fc3d21d66b33b9c2bf692ebad110425c5f048b983aca82ddd6205a96ea5a61f42e1aa062c7b274635dd3d464cc49b63c7b35639af93ffa1c1e0b05b7303abdc7f25934decfebaed85a9575dd1369097211306bd9cf032a6cfdaebac6cd109945b7d56f32a1af5b9863e5a6c69300f87144b92db6b7d +d0422b9bdd9a3edb95cb89d1eea6ca34b686a61a8b6512c8b1fe1189a3cceb7734b8482ae1a4e2e00f2c567dccdf1a6079ba89d0116aa2a70c8b53f0aee2b00fc9e93953bbaa090b4e4ed7a8c41523cb7b05d44c267994e1928eba2422f4befd5ebb730b7e544b0d51ba4052b8724bf16769114a43dcb11b02feea881d99f705 +ebe131fa523c7ed17578e2e5823da2c3b192ac207dcd0d146ebcf735dbd17459132dc47b3d16950c395660957819d219b0d1e0cca9dc6ccda229a51247ab1112cbdcbfcdaff75027336d38fba3ca3b74b9a8cee891ebf6d08b96f33d77730149e52e8c8a38900cbd971cc54987a44ce90986f2e379eb9c6a20969694ae39905d +c3a99a38a01217be7d6eeb8e2eaa56c4a43feac43006201a3f8328de13398f452e051702cce7292789b98f122ec96cb82f38fee6ff5d92bfb420e8ed260ccace5eea797479a20fb214fd20449b012c178480a35d4320046ad3889f1ae3807a33ce322ebc5f6ab1bc8f39e05231db9e61d97f5aea8bc892d32bb98ef692689eed +f5ad28c75028eca2c03a38cdfac27e29cb9c4b99a15571a6c1342a9ed21e954f5c1f442b38324ac13951f883991d85c7fd03821a45dccfbf076c03114638af9fa416a2c71b12973019d164b04993ad85102a9db85f8bee7b86df5ad9fdd9cb89dfb07e60d48c0ffdf68a86760c77dc670a1b3b62d7886e4ea96f2ff88878db9d +cff89d75be266af6afb6b9eea3e0a02825b85cacb908c9a4911be00f3b7c8c5370c05c0846979c7fa9b2b18fcea91703b6be71912927d49250ad9237a59968409ca55cbc08ebc54ef98338c59b8600ff687733e4178dd09b49bc9570c86e405a1f137a888c902d729cbab861ed5f965e1e50c9d8c3b426d62185900429a22125 +eb8936415ee74a4aeb09de49a0d7f4fbdf19223bacacfbaedb5c51c0c8d52f6c061c606060d3f9119a4fdb7b4f17b4a37b624392377ab9f81d769eb45495272fe4bbab7d110c3fe7d86d1ac2d91753df8915a8161d2f7db2378e886dfc0fe44f49c4fa6bd601c572423a37f5f9c3f40ee5c04c8f6cb5452273c0d2cb4040f0dd +f0ce9f411618305ba4a296cd22040713246e2f3ea1f723d2e2643b9fc536a864458b48e388e542c360bf5917aaabfb2cf1ce1e30d275ffee99137dd3317e19a2c534a6113e3d89a6665e55902ac1f119a0ebd3390ede13cd04792c89d349fee7c66f17b30e38f78811c81d907e275167b5c3000e58be7bda033c500a172d889d +f7745942de25894a96defe06117eee661fe59b466be237cc66b0e3854cb6d3b9e97c8b52e216458c6e9bfe9303299ac6294f2d62000a964b128742616a726c89505f1d2f493a68e0ec22b80a03e0e478bddd2760b474072490ef5dffa6fc01410a7fd4cbde2aa34b82172deac580cf3c3ee442a3a096597dcd8eeefc285b0a4d +d32dd28cc369ac18b8a088e49062c13f8a344b83cf354849104450a743b6adcd27ae6c321068f49a0334aef4896d83df1997b865f658486421ad0c5773652236a07a8846ec484eea7830c30884e7c20c35d035bbb4b47a112cfda9ba84db9b3dbb0b0edde6d21f8022f5979b3dc441245e38bc47b817ee3b0be50668f8b45cb5 +e26f4e6b3f3588b49a92dbdcdb3e5056703af21b7cfb521d62eb318105df1d3ffa8001629da6f5d3429dd767016ab9707c009a4de738b74401ad916a4f364b10abaa44471b1f16fca5c12a5bb31b6a54f1431411b2cba27d762a6914a6d13b52c42b3ef5838cbd502852bd490fc9951505f81e8dd6f10270861d091103ad5b85 +d640540fe9113341d00aecb996e15420c007a758094e6e89d05f80c2fdc165bd75475286235f5bdd659227c55bb901c2e55724c2af4baf1b989c71cd46393badb590c58b682f0e7f0ba01359232b21aa0fd2cf1a8c71be06739f1237a7de275ab4fe4463db572bffb219e2fd11b8aae37d00227dd0ed1fc060f1613d98d8821d +dc86ed947a567f74bf4f8c8b2f32654a0efff484437a049772e6817787ddbdbea1ccf4d61ae351773d92078f2e2fc788b6556da2955203b2184b0947449ff778359a1fb91bed9aa62885e5c4e3f7a359185a6816c95be610ff82a3d528cbad1775884501b5d5d200303249deb845a6656d066182cc893f0bab7523a5f8ab8185 +eea1ee526723cd0ecc2e218d71fe39bf912afc094eaf6acb4b3f2d76dc104cc9dc5a59cdf7a18493bd90462eecf9223ebadd096d07ea4f03d680f38afe3d60eb8059ec466294580ea9ccb81dcbe840fbf7b65b8d15d624db9b0b9c84d0c3d2549e3782fb1bef4e264bb3bc2d1664c140b4854f513befc9d48b9c13603539220d +e12113c4525a41a9f3858d26a91cd61061bf7976f1090934eaad962220e176519cd512c103cd4b655c87f83dbcb274be6dfcae131b017ea0c3df253bd048b8498256d2cc862eeb4a2d957d9f3c6c746bb2e7192c116efaf3e3ffde5af9d129ee65f3ae419c6130693113f3be41af7f8e2d6832aeafd2647544eee1e6b8aa816d +dbb906ff42edf909c7c1f3c280b607743049440761021499a03a9992de6ec17bc32458e7d697dba61f747d0ce110a24c710d00c597316f2d079f1ec9de3f6225f3940286f4be61fce0ee9649460ad389423a25922015482a6da7524bc65280bb0de9f72c81e459d40706d318632d4a151be0f8ae78239de005ff723ad4d88abd +c82ae8d45b214bd7cde7be84140b8f80b3180966c4b154c6c7d77b94667a3e710ea5dce00ed4a048a8f541cd61d487d014d97c0da902c2ae55a8e8eaca23bb23dea15c68a9ef146d08de1cf61dc589203acaa42df4e1941cbad3d338b56091117af1c9a23904c3b4b7832482310c0e2f9261b1b703e3324418972d903881e135 +c0a6505471e66553d80b32defa0199a97d57b22af9ce17e2a2bb7eaa9a0ff64e76a5d4e05a982d51b8db2e9941480de002035f3ef566f10bbc035b799c03ec58735e4f590cbdb14388b84328d33c53844b757b4ca44dc3caffd9ba8fd6b134da06e0d4c9d8abc88ed43808d73d2b2fd4c6d4e8cd70f91b22ee246e2ffcecc24d +c130266cd4a28926e2f8764efdc55e59cf3e936c5b244226b728702fdf5be181ef9cdf6b4d2fc7046236a741b7b9f7a7c61133493bf6b8578f990a80e68d693fd07e7330644b13a35bb2041d7a0d83a0ff31ce8382d5e197f22826930e7d1eb99bc2ac85f7036c54288e64bbaf60b2460a58c962b028a4b9dba26a9ea65eb54d +ec0a61da39b2b0af9b1b04600ca6f3cfd5d1ccae3970f641999e2e04081c2edac59ad2e25c9bc2babea9afdaefa585b9bb094945d75c2651085e67350c7f89cbd1618129ffcd7f683a10d2de3bc76420436f23967b29d00c613e61b1950384d361170a8d6207c05fa6015cfbc78d4de334a372a94c2372232d56a14c095078ed +d95927e4875a12ab9e97d72bbe3792ffc100a88abb4e665b3de5531f6da18497956af30795a8219bf05ccab568333528059c85e1e1c43b28811838fbb19e4568a7adcbe7111a260562b7feb89e9d4e8c23cc4781004558618caf3984cf6b1c0f0fd56533713b855781ab6520e30e1c33ad34cd9fb192d302acc396f65ebfd82d +c32682f151c85652f533554a95f4c5d1063c73750be7adc84cf437ab072fb835f42fa4cfb3777827d22ef6ad96d3e5ad2a3022464a9be7d861b0f0815e3f678274bf86c4ec012082b46a49500f92cb7db69df1da1b9fcd2cf4d47ea28d6581adefa9aac478781f74ac7afa1ba709baada5d0a55b84446b849331bd450b9143ad +d639fb704008e9fe6288f4a3c1b4e4bb255af723f5a222eb6b17dc79eeb882254c07634d9995fbb231e6713863185102194217c72011a1aef91db92d101dbd0780f23f8e281156168552e2fd7910c5d31510ae75564709c6ef3ca59f0af02de59d7b6b413b31fb17c41d9e948ccd2d4b1d0ea9ed58cd2cb64eea4ccdfa7a591d +ff34ca1e9b2c4807f0c9d8940074d34ec8902310de7223053d8902f3643800ac916eb801f405c6ca4c3596e3545d0f6b388c4229b19638b82057826bdbeb1c65c7557848ad894b30e336eb812a0ffbf33fbeb42ed744c7199092d45178444093d12343937e3c356bc1eed086a2a6097bc99b1a18e5d3386e6410d451c52ac9d5 +fa3cedabf5c5865d9609117f32c1195a35f1f66144f2d8b7bc45f93d03718b9feb4b3bb324420c274de0adf7538d003d689de88f19e710e0774f6c9d02bf1e3f4ac646c1f2b05a2144f5bfb6bff0b9421338e01911c39d58593a13d5f09488dc0517cc49a94cf0e7efe39069ae5ea553efad66f049a3a1484bd6551a98a2c4e5 +c2a7edbcaa3c4b5539b1667c612d3aa11696347b7574722a520a30336d75f3b51cfa7bd8bcc94f393beb73cc34c27d7619d851f2b8c1738c87e7d502c2dc1fd979e66ee2561a92281f4d100a4a3a89179cde82303385dcc4c9f048f399237545c526e03093a55fd90a35b433ff86c635041674490876a0ee3407e13a4432473d +f46990850241249bbb7cdd181bf26bfed6858152d0a2f3a07e06015d3741fe9079527c881465364f8dbdc7ea9df72e3bc86b1534a1b9a9e9b0db457753cf70ea06a3440bd1459554e247bbe119e789d2e0f4857aff24f410a7194521dac382a81ce89040601cda6ceb76b96267ea9063777b79b32712e1a1ff0f8683745a576d +d585d7c8a09e54f83b1a6ea405693006b875d985f01d9ada9d414a44aed16c2759609706a07e926d3c903ff6abaebbe89855f4784de2975096f249508d4a3c2fe55f85a5d662ee4a48b2c21e9f862056bc6b0a802c5130ac4fedfef94bf402988fa29bf125cb933ae316dfd157bb1b4d56c12ac3f5ce2839e41cd8a80c3db045 +c97bc84c797cc5ce3c2be229b0746bc45fab70f26b59cdd7cf7a5a0b96cb7c1e5e6b97d743ff7acbe33f2356a65f5a885d7b0364474e2c72bc9d21099282bec72d23ff3812c2dab68b7687c8b4a49fc6c714dc935f69cb3444430ae719cb3aa72bc80eefddabded582da7098252dd8baf3b60bc3133c2dcb99e58b6ce9ae77cd +ea3d3fbacc5209a15b9321aea7b43727165f34b45fdc06169ca953dedb9b56a3f71fcee48217c54cabb6813e36957ca4453019496ffd665109ce2096dbb6ef049d7c47bcbf461532069522caf053940df12971d7748caed05e9e654110fb97d199683769a8e2dc7666b9bed501c9bc93b901334fccde993d646f9f2ebaa0b435 +ea860c75b83bb20a0ac27531c1ebfadba1157f1f398d39c0c1bb0d6ab81ef2889a400e89341712ae52a4e0e155dd2e2db41863330b02bf198793872565b515217b33909de3f12de190cddcab5ba8ee70af4f29c86273a62efe6fff135da9240667bf7d2ad03ec6bfa0e691967d56da9bd3c57ff9790ca2e905c86fa142623cbd +eaf4e7490624a6174c26558a38fb59f80fd1e0998f4a6ab68a2b02ff3a81905576bc378f6d3d413926888c4067959b51f0725f854fbad6213f7c99416cc413dfd90c814e11fdcf373864a2197bbffa3d1f30a79f008b90bb566a001943d37dc135eef8d10448218e72e2d95a7c02ae89690a6b1970b7f6edbd47419888210aad +c67db1f755259c3e502629df50c9e52e55a8911d237797c614b8e63908e5d3c1f13f9fbef4a6f54b56d8db3ee99076bb01a34225c31e316ab65de36beb85753384bc8979f19e54692d4312e0a1ea82abfdf1fde7963f05d811600311866becc994a1909603d29d90c6bee021b06952c1ea7b99d3ac4bfd0023bc88698651b415 +ed2741be0f80765dcbaaa2df41b383b3a66241743a2828fb34e2f941ff6c507d6a7dbe8706cb1208afba66b83df09562a52579c54d8889220d44856c78242722f1510181313931892ef29dad2c3e5938ce3e74ea24d3ab3a7275eac299809242a1ac425984e0520f03991342fba98292e672d99a9d0c063904428badb005eb95 +ca82695fa012d5e6f3c664b23458fd5daf95c94b4299f936f8b70b6bd79ef243b1b9f16443f5f8945fb01eb0beee10c2bcca4225e6076ae9f5576168826442d4318afcbe7be329b30f0b4becc72832534fafb6440998f31acb31258673a9d202d5dc5e1ac0e5f282c61eada2b6f592aa2393db06bcfcb8166f3439e01e62545d +fda28487fb44a1cc26896298f6ef49d609087687498713f41befbbf6ce0ddee25a61acce094feb2d291225b00be8fd93ee8ddfce42999f29b149cb00f36eaaa3d379e9802f70c3ff58858acab0ed34bb9050ceb4281832a194831bf82d860e27474fdbb2f7b66eca12307dc685bdaf34b623eafabe885c269bcd6c21a52ef0a5 +d8447ae18777fa8b39f9077b58e056dc22330314c427e6e8d13fc6a3610a2c1286246a724fb99312e7f915d891101b1d8815582165178d55bd4a2c367c24e78ab21b13a8b9cf3ff67541fe69049948b567fb2f2f2bd4e7c711693dc0b6ed7ead617a447fb5b5bc567f53be6bb0fa097eab097d91077fd6ed1f02db4ac96575bd +ef71e9bee6899aabd27cf4ab2db213d0ee49214291d073415a2663e370d01fa741495af57193e52c58ea3883b2a13b79d85c68ed4032a0fe96e5c005df2b0982892f1d6c1c425c04063122ce306bd1a194b7b5a1366c2ec673608c56299f521f0c3493e13bed9df1c462e36f3a0854ce33926d532a3c05af710f5fdb65d36cfd +e5359c379e60c97dcdafe5a336aaa0db6659cb8f806a5195c7e13211b396324e831aacbb8691146ec906a96ba3f66cca0c8ebbdab0af793b24c94081dbc19d8f1ee6625ddd16103bf49804fe41525c839f47270d6f1bb9930f46063b593d48145c1982a40cc78421277ffa9b134997b0a02c8af22a51d0c83333433b3fc36ba5 +ee72e1aa567796208b5d8e66fedd555d5755d9c353a5d1979d0bafe0201ada1abf26e9993e2d1a20fa6a1f374d8ef39f007120099df38d6481584e6c6df24d31637d5a4d5c92f8496335ae00a3c7a5b713ee5ff12d9c4dc48e02c8aff9a308592c8ed3f66c1128481059266c4f852540a1393139f7a2d8d4ba6548505af6f135 +d95444b1c9c3d55cfd17e0348d0b59c73d95a44621d30d3a6fca261a8a1a4fcca9c3e4c218b1a88c2aade830d7e74b558ca56446147f2546fc50a485fdfedc0e258378ec1364edcd99a44d4c203b01db566b20528da4c3ccf4593d388fdd27d6400fc1e05bcafb03ba5b59d0cf3edfc66c172a6d79d50c9f6efd6e32bea5b0e5 +f409c82f06463b8a59238727edc9d64a88747a76a4d8a0950533a63664e5c231c842557172601b388f3566d8ced5ee0dcd34eac2d1fa16ba38efa15734ee29e4e42ac00fcca1a9919b4c7965c7be46a72bb6a3a4539fc9fa9f9fd3732786ade282a4fd6b724c2638406b97e501abc5fef1f34b9a4117b54cbb96212cfb0d154d +ee71503445dc30a2e629e73523d04c9afb0ac5bf8c93dbdb701b6d4f95faf5f619aeca3cf32aa52d7c441043c6d08a46f20ccce3b63348fef6e5c5ea655a25364ec3cb997c57d88448b1eae83f65694df426c4b265680b8035a589f309bd1bdcd77615cf00fd98f989b2c1f68253959ff6e45e53524b49a6b81500c3b1975e7d +e8e6b89a01bb23b1a1e501e5cd91b8d7fd676e3b4c82045b2f3403893a44cd2beb9d1e72ea33ac197edf6838c445aa924e0174a83ef14074be38957f494f7aaef38cbd6b42ba7a3a3e4e570f0c9fbd0b9f0876c12f66dc7f2806341851997d623afdf8e1885126cf64e6614119fd9096da72f8bc765e87cdde95f796e03ac72d +f28d5a3c2f7f68fb0fa309881612184933794a4e09b4a914d0e15962ba28ecdd3cf032cc79ea4edc98f96a4d97f9ebe1a42f858c58db0a88470be1d9a2f15a3899bf7ad8703425ab51d37fc186578bdb269fbe91c83c99a5763e433ae85a91559c177303a06655300952f27438adf16897504c23e334f2ad0b9574714ff525ad +c36710875e7737d6163161d4aa394fc388baccf567a9a694cfff56728f5a5a84818d4b4c2a2c393cc92c4e59972980407221c75bd06253d1ea5883729fca08ed04a37e2fdae1d71c00ce3e5ec49ea516e9a43ed50dc130f9ca82a93c735fcd9b953893ad2a2f5dce201db07f5625fd0c09cf357201cdd071cdb442b99ee65635 +d9fd2b8e5a92de3cac06a9b941af8f6734c834fc586ff9664332272e5df184d6b0dadba9e1d75800bfe679a15caf98a340b68f1ad405cb1b92e1a0b5f176419e72874d162ce0966a24c15bd67d416230b07daec55774e40e130f5b59ad8cd81880a15659e30eb7c23caa315c4ddb1f7fb4d622b9b07900b28cb2c8850a9ead5d +f858fff7b6d38f73bbc3118f1a67e787abc04c759a97dd8ab894f1f4c70cb7deedc9d31f642af1deee7043deb93ffbb3cb2a50cfbc7de9345a66023578f8e168687fb8e54374cbc48b89d41a0c8ddd5136f2ba3119baf0b101d462db1f7d6adcef017b6ce12af71b3d83d36871836309ece1d2dd2316a7a4165a0c4936e4cf2d +c411fd6fae60edfaf2f378edc643faf350c7d5bd8d3b14ccc5024fdb2a720db6da39aeeecd2ce1a2abf2a1b2bde9a9e734f641bc1fbaaecf4eb979cdef4c72a3b735073ec40790e1b264519c00fcab517bb14e65721d5ed8e49af4d45cc272f98f9ddab8126322b0ed77f9dc830b33d3c0d00f7c989f000f5614f7e2b7a2dc7d +cdee1cecd0e500ef3a24913c8b4411fa864510348618d0497a27fd62406aa5e19256fc8c28a5865e2efb24b6e56280ace90eef672e2aa250355e6272218b50ff24351f52a9b6a95f3fd302da49668760566314b82dc4bd36641e52c42622fa3b99b0b6e080d2a6873c666757a809beb30675014a61ad558e02dbbbc931329735 +e43ab2cb35c4b7db2c89d68b1caa3a51e5939c423a7cb3cf907c66cb0dc17799a936cfdc74f6a1aa1ea1ea7b74640105152803015ca083207807ce0b3d27310689a15a59f5124bad92b0d7d38d81868bd8415f2ce12fd6dbdfae8345e30e2d3e481f736a9bbb0348c09c521b5a95595485e5db301d6398ff04a9dab2e17097a5 +d4b4aa3594a5a3764e984f8cf743bb10a9054ae512660fa39595e09b3fdaafdcfb25d814bf548fe219a3c932b85d1d05b6bac54704ae7b8d01b126c09463678752596df2eb1a49681d4eac1620718ffa9e1b383639f6a7e02bae1858ba20782b65b34a2873a7b20790699b219f6814edad9a70e02aa2241944fb548edcd38f7d +c424e212cd8caf79d592aba373255d335bb58dd95175bad04c404df2f49004585dec10629ffb6cdeed6a2b96f00e6a943533c05571b10d0f977f5ad6a63fdfd57822e7c9d83f7579cfcabdc57646dadeeb7e774272a2fa5739f9ee189d05ec7cae84894550e6b62cbf5364a9f125f23e6c66c4d6387179a480c8ca19a61a3405 +e35bbcf0eb6f2fd2bb055cddb9a62008bd11c72fe35f75f2f8dbd4e89549cea92ec4b559721751a938c7b491a79e7341db2f3fc9ad7210199fc1fb43a2d79964a7526a1f22130cb232fd006e85efbc33b03a437fc0806431a5e55fc3b738457c0fb9c2ed38d5a87382573b10202404e71dda4ee520568e860a2c5daeabf94d2d +fad58a9cbffe7e58a6fa508dc7fa68c3d16afb32593c74b324a96953e0a28c855cbd40e0c4edb5b255c3ccd3ebd5dfa03ff16afd76cf910cb513ffcb5103b87728d1d9f46c81f2eb908b4c35321aa78df4b4aebf26aa8ba4d7d9f4dc7817c5835a5cc1f06472467ac0c329952312829ce154002908a0312397d2001b22e55a05 +c2cc23eec815b9500fab0310f2ad42967b1d3a8a2ae30dc2e0b0756f03d15b986dbd05ae733b374e687d4c1ac71afb3062a0802016cf2f861c138aaa082570be4e3b9a3d8c3ea9d432375ce5672eda0d9264588ad178679401b1fbe8d39cc6d60866e7f7e672d96683069ffffae0fd0f7194b73552c2d37144d8da4d8f0347f5 +df830ac28a2ceb86de86c778400c44620fbca0ea597f2be44d138bab5d40d89ce5d802ae39b07186ce350ba22c05fb614af5d5e3e8796623ba2838bf8162bbfb336e159f9236ec9a8164cf7c59a59fe1309a4d740b337a4a0cc9d8a9d961d10e2a3e5d2f077a33edfe89721c2c53b238e6518d2d2104f2ccf3351bf73452ba0d +c390d2db5531bf90d8a92cbd10a58a255ef6c8d726b7c805479a5fcb0a805458da99c0bc9123aec25e4bbb483d7d2ab14c879ef3a278fe446c03235fdbc83c85779297db3ff92ddcc4c5a6f6372e924a5d24f87528f87f1f6cb0515bec718ec8b2f1dd334a48d94ba766664ef0c68b9d4edc80ab067e0b642555cee16492c735 +e9b097742abf5024caac24091c2c5890cb2ae2fd5e9c7128c961d19f4c5fad4bd763dcbf3c646ea3a1ac8d816b673af4d6a488f2e40ec0100d154d6d3fbaffc444bc000255950ed13da1308bdb6a8ee6bb3468564637c3c205f77a3ad718d7e90f02c19b6e497781d8da8053733492dad5d55db1b7b84ce21260c85dfcf4dabd +c29aeecd959ee5a8028ab5bf1543d47d90947a355022ba3c72db9304a49d740e7a3174ed0f56818a8bdbe015f7e11d05ea8b03a8e43688dbe0d7816fe9cc7311c546ae34c29d304fd5442fe8586a89b78994d121b0be22077879c6781c44f124a3be54e2a6fd72482777d63033536b8c01cb069c7ae01f16f3fc76e568cc5bd5 +dcba67abd50cec07b4e84ff593f1e89b7e30b28d1ba0704549a0f1de7e23327a8c997079464f0cc81feb46e3465ec010632b9ad0a085a1bd2a5e8c9778934241c68bfca1c96e476548296c787372e8057e7ecdab83493619ad567019616a53c19818228420509728032d8618a8f35fbd901fbd0a4c294a2ead8968ead89a1195 +d33920afbba20c8705f47c812f31cb7b36c7dd5e88a00ac9f555a6f0dac9026c4dae15c219f2760ccd38c0127671e5a33f00211c81343835d8cd856c93e9ff3a6c5c61730a7f388f6aef7779350ba98316f795b684c60950a18e52855288d2e7575315a5ed17bd837e176b0020e0d47d9c50b668a73c893289d66f79bcaffc5d +dd4b3b5cd4c6c13f1d180f2ced8fd94eed6df632f0d6dc0c3a86b08c971daacdb45d96b2df9f1911c8486a06fdd64535d3fe012c63bfeaee833e2b6a220e00860fe9360c9813f59c13dc1037addc9eda6784ab2435400342364fdbce37baeffbf4fc4d876eb10d8f48a6604d85609eb172939f57584087ca911511371ebb43ed +f445fcfdaafc3b04890f3a9d893bf0bab976d6ea0ab6353496c92a35812577970a6f0169a2f2c88dda1f8db9e5a48f1c8bd97dd8dc271321d4a512fbc1c22f8d433ff4acf7f07913fe3dd61c8085f7fbf5e38c73cc0bcf7143c7e7940bf891e48bb25e85e4ed044e299fc73f8ae5cbb928c350db712af57e3206075c31d64dad +ddd27681c4e17b61668296dc2ec218f7745b0d22d93b15bfd665cd1e2341685d1e46c2aa7272a81d2d6e492c879ae6d5bcfd27bfec68f86991448db24eb323b1a9972403d716074cc0e6381f58a9c414b67b53b86a0d4e572d117e31e831eed78674b63d8b53d8aa689eb629cff0625c90053e7de0554f26325affcff31c2295 +ed16929a515a5c173259fc7119e5b958b26a2c061788e7602bdb74df932bf38eb4f2864e8165d404f4bff6d1f4a4fbd0706b840a71f36fbb97d7da21ea11cd258914e1ad3c91f480154e2dd0588a52d30bad58a63da178c980dac5dcfbf07930cb7032bc86d352634c042978640ba314ea678097b6ff6bcaa5e76b5714dc6c35 +f63fb957a8f763458e2591089ba4c4c729bf996617e81bcd911297228a6b2f4d5f60f605ff5efee7513ceadfbfd2e6548850689fe19dcd9967787beabf44400c90d6ffa22874f1d14fc0132f56be66b3d0c62acec6243fc34a876f16b8f5f71564a58bcdffe30455573ca1aefd3b9fc62886d1ab6456de66100bac61d0c24e35 +fcc63fa090af719d1a27b6345425d6685aec8b3b8dbddc2b02e274205c91c965aa6e17761e448480316712a25b33a36ac31d959492c29268ea3f10547f28e90cc8cb597016f1f126148398e21920ca71960481fce3f6ee4c8064bdba7ef49af62cf3cff00cc9ad475ab84619244475378066ef891155390ca589b75efa544385 +e6da32d30e3934c02eb23cb417025a288538ccce07e0d9bce4de00d9492720692be2a48e82ac9a25144c0ec9b4b141c77648c35884316b311080fb0796cab75cfb93933a2aa9310423a7b2ef94860783aa27f3061246a8c6bb2e2b40b69fac7fb617d24d1cd094abb1a1c7bb46460598e66bb539aa0fa499ebadf05e151716d5 +f7379a553d60d6e51a8f37f2d910d9dd5256655efdc891a708c6cb52033ea4689732905a5bb46cc4d3183e74708578e39b0c8630cc0fdf50e5355aafdf07b478f19584951c251fa72b93be1a3a3b744fc3c911b0847b089eae9dd73ff7050a0fefd4508f549c37790de86c87ef74bb53a29800fc64fbe7d365e7e708dea86a45 +e933766d7ca9db5dc66ff2ddc7f44542daf51232fb9ab413b1d31aaac02dbca7113c4ca874ebf599363ca99572e19a3fa57761cdcc600ac6d2f0e8dd8471ee7fd1b5584f201a480ded805af6dbf651f1bf1f06757a7fafec243c30ef5eb3d94958ad6d6b9687689cd578e383c3f6d8e3fc8981e83a91dbfdb2c4e5292382a42d +ed0f5d59bd470fe130096bd507795c809d261787ce73c77de9480d57985759d4909b19b5e248bfe6c75655beffff3a28aae22c017ca4c20ca4dbc81288542fc5b6acb4df489e7a3895749d21f2a13c0cc7fef538dc806576dbf816b529c3800eed0dca00e3e4cc022dc498f8095c7f62573daa7c00b6a049fe550b1d74a78e05 +d647d958769ca155b5f98f62fb98b28c48bc228f641b7f0a05ffa07c35a7413e29f35fb675b6e2580bc1e37f95eab82aa64317fdaa73924ce0970434002d70d1a08f84099d1b151df7623ca07bfe27b964f2ef9796d1e48c172c812e7c039484c16df56e289fa32f8069ea99a209b23efc383bade2006ae60521ef2f9e7c28b5 +c49923c0119e93216c2684dbbd9385f2c59c9a7e6330a44479a62da7db661ed2a36bc6c22fe5a0d21fca0f8e0f2d91a4c2a5c42f917f8e8b8d3e33ce97342b2081bc65eee931d2659c5d7b997e74bbd005b91d1353a3a4d05bfe6d680053092f27832c22776178bfacae0117fe6d80f42d5385c38e0fdef4e3b8cb33016c4fa5 +e588adcbdf57002875cc72def03f19e6c24059914c3a6055a7d67374a8ba3d339ffa72067c69343ad5dd11001e98054928cc39ce04b543ea737b1735682cb87a9b82963080a79946dbbaffac5271f905b7236c6215a456cdc3c5c40fb8bad8ce33e67c1113cbd9f889fc785888f50bbec30982fbcadbde934d72d44990b12f9d +d36621350931f1a0d1a8b1d215c643ba1b6f63a879789a7f5ee272f570e5cf0ec06c0700fa2521e5d5799e091967c54622534dde1c7dce3fe659569320fcbca304499286c3798bae6b70f64b72e18cb4ef5884de2103661257f61d327667f7f63ef4d63482e9ade53bfaf117662b65e46db4a2f3eb0829ee5363f53d2ff38695 +ce5e2ed6e0b9a7e749f48d031452c9c49b9760dd74e9cbb87a3e6d208cdc657dae6caa5218e0a1e6118080e8d2201d541e9cfd9fd518ea91c88cf18d27e484f0ffd0d9d04713e6a6325df1912ed4ef490d1f8223b884277a45c18d9157f8224f9bcb68d4458b79cf80911990b08b40962f84b5481d08b834ec2b80b81d93f2d5 +dd6ab77fdad44b520ad7796facc9fc57e52a6adf9dd7acaf00834418d871f64ac6f2a44d44578bf2e4c488b57becb233fc3d1367b21227c42f0cfe256ddac7712556a3b15c9185f60093d07835e98d03c82a3b9ad8ed338a2b54d49a6d5320454be8aa1c444cefca7eeff7c3854bef4685e8e56a7a537b7a3cd088953301652d +def3aadd465c6faffd363a9c360eacce5859476883c48dde4c8faac7dfd58a1ebfe2316b8771dd04553b78a11d2b4617797fddb541f1e440b61ac9d1097fe55f27be65736448206d0349d2cd95d8856bcc9b770472e8e8db83d3ef3b38b40b83ffb2eea7c0f7596911fa79b320e2add7c8336a71dc1a75e29d415ba0bcf24815 +ec4150c5b4a666343f6b2a831f368a7e0d0cc7f64473e521f539eece8ce65065fc2b9c1484dc692c7f4999e766e277f6fc6d1beed8c64d807cdc10a4ca6db1ac8141406768fb4cbac076d77d9d0555d95fb60f878996a366b099e59952657823304a566b4009952c37389482e8979a5cb0a6f1cec39bc88442c91bd918187ef5 +d1b84e4ff948e7748adbfab581176b13a98fdfaa6097ca3615da0fddfe3a13134cb4737e440dd211976f4753cb17359ed5a4803e8fe8f485103fb47b82c923e4a923df949aa1339ec6e925bedf405f05863e2628bf3a2f4a301426e97e52cd17d5de113ed7b73425b5187a2442b141a15804a0e782528dbc545dcf90c1bb5edd +ed83c3fe0acb80253190a59051d684d71c8eb39fdc8e8beb75e0a166438e206f9e060dd6de4aa9569a16fd43a6337e34f8b038f19906c4670410262fb3cbcfdda0447e4cbb1c69bc2ede8fe60b0bf40ede40e6e380a5a16e8633adb18f3dc12b2e7c74e6dc088a23cef51792587dcb1ae90474f82f37c653d2abfdbf6350229d +f25cb0386c6f7d01a3aba79f9400e2e621a8174de2ab436650a9354c2ad0261db1ba8ebe694bc45f4ded8184ed410c53c796286de4e0427a026140f2a183891ac0422c1247e01a793f94ec112dd23b5c460eb72356b060b3cc701c8db7a9d5b7cd311048f3f7694a92da2fd07a000e56277ae75cc9a15e71a81224592e959da5 +ee03c438fc7f8908610430d2cd034cc01a6762d94eb940b5ebe7c227091cc64878d41821ac3e42af3149e45b4543e34660716c2cb49af0b6c03be8ff178a242e3b5daf281aa04e2ddacca16d65a2b065a7c61dbe4bd8160d0a4a005679a4b5f0cd3068e1e092304d2a585c4fb2176bae941fb11374d6bc0272a8513865cd457d +ef6568752b0fc3eafcdcf2f8ac2b1a9f774e53a131eeb37d49559cc60d9caa99d8bc777b9ff4e84702eb83165fa03627d4eb09d286ee42565e87da20bca80643fd26258d3a060206faa9fcc3508ec1537f6578209ac359f544529fd87c471635dd9db44d3ecb9f5d82906c171673ac1d8ab5fb3f1bfd7b3cc2c06cae9b7f6685 +ccec545b7d7f1ea51d8774cdf81a6e8794bc3cd87fbe1a8f8251d9741410b37bc39f6af6ba9efda0cd15243eed15cf11f0b4465e02c38acff963f71fa7220c9d52f64c2fbb8fe044bc6cbaa0895ab8bdedc65a89e0441524cbe28ef9ada6c63d0431583506354b9c2a5176779538bf229b74c8f7feaf5eebdf0825835f33aa8d +e4459658218601a13cc808dc9581fe25f3609976c1f3430c813a2b5dafc902d5440809e75b1e01568bda0d15f8de12f368d7c3a32bac5bd3781f08b0beaba41d4f0541576658fee91042aecf2a450aa0a1612010690c291537a9430de782eb56207da17b54c16e1096eb1f9799ec98910c8557a65d4dff8da6201949a9238715 +f62b559ef3edfe69b2ec36c3af8ec3c36a326409f7d8665ab2a9c26cc28c9daf5350e8164e06966a68e33ceb550504945fa967c6af820a49c4abf6076f94c44340972f524fca03156376720f5bd7a795a4f1d022f1d47cf571d2d4d75b677791bb31bde0a3613d289d4dd1a3da76b9450b56efebc996ff1a59eb3d42da77285d +f397abbfca0f6d6ab5c132ebd18a30c83514b2576c2876e20c6cceb43ae8654f786d9ee5d8ad7b968ff447274d8c082425a477836b59bd27db3920ffd45ce0aec781852cb2a4cba54aa57092b407e2558f27a8a4a43551ab0641b4446fb54845c883dcbefed352cc0f7c557f1597f3e360e8b5d27da51bfd38e7454d509bb19d +fa306da03ce1f59bdcf895d340061798b11295da3078bab00636ae87f758873c32fafa2579563cf2d313c0889664d66e10957e14b0d90af7915cf61151043c1ece2190769ec61bfad26fce27a86094606f734586ed7590500f21ef02db9b19ed5b7b9598396d10135febca8c3e0be26ba0f02e2e54bb6b1ce0a7e424c4cd0e15 +de301f25036944a4f6a8fe11d1d6781cc5e054a09d449a8b1443ee4ad50e9ac8e68e244dd8f8ebc9de0f6e3fd2bd5de7099e17c452631f1962ba400eeb79db5d36dde3f91c7d5780b2ea421b31c2ed57f11cf08c29bfdfe7350e3a87ef477e0d178cec6faa7a4c07519f5fb21661a9ba681906dbc2c2658d9d25bd42e436118d +fc1556bfd9852204f19ac3da8d59b2e889d4232f00afae9dd890b47882c130eeced040fb696842e0635ed0530cddb515054dc514765e9b555f9857cf9bb13cbf5e2fcbc6630a0989c4b2fd565d81e7745851bbffa65ae8ba42591a17c3a44e1d8d60cd549558a4e17bf5343613a2aa4bcb0d086588579865e14b696ef5d03dc5 +dc60b41e021104e87cf43ba8e75dd012c1121bd5c3e682b8efa1f1103a12e27d89c520ff95809fe0bd206ef70775c78a2364d01d91f4afc7c8a8d02a671e14e2cb1df0b14852e7c5134a31b4380788f8b0f37423ed853e3e1c1938ad3f7cec40cfabaea1eef28c8d2b01f6bab2a1d584084897801bd249147e6e0c725eec7ee5 +ceee4f09a49f1de80b4d0dcd33eb56e8ea3d85c1a2e5e856323c03253fb91e2b4347857a86aa1d8484a501238f10b7aaf4adc3c39e42dd04495590c814f6af2c6a07155b1a793cdab9067b7e709bc3d748b10a419fe3f530111444a7b8cf3dba2880ff1bf81a607ea367b5a81b52e16b41080ea36b18a0d3590566af84989945 +f6bc6ad26d71863b9c771160344c9aa98f35be8193d2ee0b47d342a9ded78aaa6c654df6aff01aba55fe283df748f12afb40f6556d4370a9a987b98e2b330c9576f76821afb9103f249af8d6544c76b94d0e19b710465b5a8732ebabce87869a115f7cd88e7c01dbbb79c9cc04d266b9c578a645616e8ae3d8fbae1f80667d15 +f295e2280717c5fccba279523dfac2149274ccbf9e7a6ef99e17444c8d4c89c668d0306cf955ed951b7f60b1ed3470643fedfedc01cba6d66c2f32ab122a83314e84e21e1bb1c1af7ba69fc64faff940e0e2a797aa758f8b2b3bf2e882dffbe2bbe2da6680e622d05ff03a4ef09e88cbc3595179f68779062eb7fffc336ef025 +d607837c88f51a8449b0d1ded1caa08df6bbefad69c55cfbdef7c7f60fc0b2b3851019ef5be975f84238082fc0b1a1b67d595a95ac5e412904cba879d5c67a99479d5132189c9cd21c1b3270f293d1be5b3ae383e4ad9c3e72acfcf357631facbab5adec457b11bf6eac2cd2995a28ae5768ed2dad963bbf28b5794eb082d3b5 +f18ec69d1572c4686076d8f7f96629bc04ac315b0ce5fddf4758aace119fb5562e39535b7f20702ca99e686e229bf951e7bbb6d5cd6919f94235e873c3a47ba36829070b5f34e4153d0649f7c4aa7acf14720036b80362ae1b1063222903e4c62f434ec16c852c926268e739ba62238994dcc6f95c440d4826dcae5a5660168d +d2e36d5dc038ebddb59318b497fa416f76d2ca62fb99f8d9568737430a5946069ef251c20d2311598e9d1055f8ba15b018c28ec131a683d4d26056e67a46216dc529ab933ceae21f762538db6ca6db0473ed9dcc8c1ac880ada42fcf52938bd0cf3c528587a5ed61f4478d185c4b0d4edba24d222b207016be16e43105fc96f5 +e4be11d1cb3926427f6b2d26c43ae756ab16ea299a5c6b4c38eaaef00e0642e2c4cacce642f3be830a8fa93f5bee03a7d738b0a4e4181e0778788cc81b6989549b16ba116cd931446f39be17de2d99896832ff4fa1d4e9d70a15c4a4e7afa4b319cf51fda2ba57572b5656a6333597df083aa8278addc3024c7a21690e7fe305 diff --git a/crypto/sha1/_asm/go.mod b/crypto/sha1/_asm/go.mod index e69de29bb2d..ebd41369ba4 100644 --- a/crypto/sha1/_asm/go.mod +++ b/crypto/sha1/_asm/go.mod @@ -0,0 +1,11 @@ +module crypto/sha1/_asm + +go 1.24 + +require github.com/mmcloughlin/avo v0.6.0 + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/crypto/sha1/_asm/go.sum b/crypto/sha1/_asm/go.sum index e69de29bb2d..76af484b2eb 100644 --- a/crypto/sha1/_asm/go.sum +++ b/crypto/sha1/_asm/go.sum @@ -0,0 +1,8 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/crypto/sha1/_asm/sha1block_amd64_asm.go b/crypto/sha1/_asm/sha1block_amd64_asm.go index 42b6b1419da..76265a9348c 100644 --- a/crypto/sha1/_asm/sha1block_amd64_asm.go +++ b/crypto/sha1/_asm/sha1block_amd64_asm.go @@ -23,231 +23,11 @@ import ( func main() { Package("github.com/runZeroInc/excrypto/crypto/sha1") ConstraintExpr("!purego") - blockAMD64() blockAVX2() + blockSHANI() Generate() } -func LOAD(index int) { - MOVL(Mem{Base: SI}.Offset(index*4), R10L) - BSWAPL(R10L) - MOVL(R10L, Mem{Base: SP}.Offset(index*4)) -} - -func SHUFFLE(index int) { - MOVL(Mem{Base: SP}.Offset(((index)&0xf)*4), R10L) - XORL(Mem{Base: SP}.Offset(((index-3)&0xf)*4), R10L) - XORL(Mem{Base: SP}.Offset(((index-8)&0xf)*4), R10L) - XORL(Mem{Base: SP}.Offset(((index-14)&0xf)*4), R10L) - ROLL(Imm(1), R10L) - MOVL(R10L, Mem{Base: SP}.Offset(((index)&0xf)*4)) -} - -func FUNC1(a, b, c, d, e GPPhysical) { - MOVL(d, R9L) - XORL(c, R9L) - ANDL(b, R9L) - XORL(d, R9L) -} - -func FUNC2(a, b, c, d, e GPPhysical) { - MOVL(b, R9L) - XORL(c, R9L) - XORL(d, R9L) -} - -func FUNC3(a, b, c, d, e GPPhysical) { - MOVL(b, R8L) - ORL(c, R8L) - ANDL(d, R8L) - MOVL(b, R9L) - ANDL(c, R9L) - ORL(R8L, R9L) -} - -func FUNC4(a, b, c, d, e GPPhysical) { - FUNC2(a, b, c, d, e) -} - -func MIX(a, b, c, d, e GPPhysical, konst int) { - ROLL(Imm(30), b) - ADDL(R9L, e) - MOVL(a, R8L) - ROLL(Imm(5), R8L) - LEAL(Mem{Base: e, Index: R10L, Scale: 1}.Offset(konst), e) - ADDL(R8L, e) -} - -func ROUND1(a, b, c, d, e GPPhysical, index int) { - LOAD(index) - FUNC1(a, b, c, d, e) - MIX(a, b, c, d, e, 0x5A827999) -} - -func ROUND1x(a, b, c, d, e GPPhysical, index int) { - SHUFFLE(index) - FUNC1(a, b, c, d, e) - MIX(a, b, c, d, e, 0x5A827999) -} - -func ROUND2(a, b, c, d, e GPPhysical, index int) { - SHUFFLE(index) - FUNC2(a, b, c, d, e) - MIX(a, b, c, d, e, 0x6ED9EBA1) -} - -func ROUND3(a, b, c, d, e GPPhysical, index int) { - SHUFFLE(index) - FUNC3(a, b, c, d, e) - MIX(a, b, c, d, e, 0x8F1BBCDC) -} - -func ROUND4(a, b, c, d, e GPPhysical, index int) { - SHUFFLE(index) - FUNC4(a, b, c, d, e) - MIX(a, b, c, d, e, 0xCA62C1D6) -} - -func blockAMD64() { - Implement("blockAMD64") - Attributes(NOSPLIT) - AllocLocal(64) - - Load(Param("dig"), RBP) - Load(Param("p").Base(), RSI) - Load(Param("p").Len(), RDX) - SHRQ(Imm(6), RDX) - SHLQ(Imm(6), RDX) - - LEAQ(Mem{Base: SI, Index: DX, Scale: 1}, RDI) - MOVL(Mem{Base: BP}.Offset(0*4), EAX) - MOVL(Mem{Base: BP}.Offset(1*4), EBX) - MOVL(Mem{Base: BP}.Offset(2*4), ECX) - MOVL(Mem{Base: BP}.Offset(3*4), EDX) - MOVL(Mem{Base: BP}.Offset(4*4), EBP) - - CMPQ(RSI, RDI) - JEQ(LabelRef("end")) - - loop_amd64() - end() -} - -func loop_amd64() { - Label("loop") - MOVL(EAX, R11L) - MOVL(EBX, R12L) - MOVL(ECX, R13L) - MOVL(EDX, R14L) - MOVL(EBP, R15L) - - ROUND1(EAX, EBX, ECX, EDX, EBP, 0) - ROUND1(EBP, EAX, EBX, ECX, EDX, 1) - ROUND1(EDX, EBP, EAX, EBX, ECX, 2) - ROUND1(ECX, EDX, EBP, EAX, EBX, 3) - ROUND1(EBX, ECX, EDX, EBP, EAX, 4) - ROUND1(EAX, EBX, ECX, EDX, EBP, 5) - ROUND1(EBP, EAX, EBX, ECX, EDX, 6) - ROUND1(EDX, EBP, EAX, EBX, ECX, 7) - ROUND1(ECX, EDX, EBP, EAX, EBX, 8) - ROUND1(EBX, ECX, EDX, EBP, EAX, 9) - ROUND1(EAX, EBX, ECX, EDX, EBP, 10) - ROUND1(EBP, EAX, EBX, ECX, EDX, 11) - ROUND1(EDX, EBP, EAX, EBX, ECX, 12) - ROUND1(ECX, EDX, EBP, EAX, EBX, 13) - ROUND1(EBX, ECX, EDX, EBP, EAX, 14) - ROUND1(EAX, EBX, ECX, EDX, EBP, 15) - - ROUND1x(EBP, EAX, EBX, ECX, EDX, 16) - ROUND1x(EDX, EBP, EAX, EBX, ECX, 17) - ROUND1x(ECX, EDX, EBP, EAX, EBX, 18) - ROUND1x(EBX, ECX, EDX, EBP, EAX, 19) - - ROUND2(EAX, EBX, ECX, EDX, EBP, 20) - ROUND2(EBP, EAX, EBX, ECX, EDX, 21) - ROUND2(EDX, EBP, EAX, EBX, ECX, 22) - ROUND2(ECX, EDX, EBP, EAX, EBX, 23) - ROUND2(EBX, ECX, EDX, EBP, EAX, 24) - ROUND2(EAX, EBX, ECX, EDX, EBP, 25) - ROUND2(EBP, EAX, EBX, ECX, EDX, 26) - ROUND2(EDX, EBP, EAX, EBX, ECX, 27) - ROUND2(ECX, EDX, EBP, EAX, EBX, 28) - ROUND2(EBX, ECX, EDX, EBP, EAX, 29) - ROUND2(EAX, EBX, ECX, EDX, EBP, 30) - ROUND2(EBP, EAX, EBX, ECX, EDX, 31) - ROUND2(EDX, EBP, EAX, EBX, ECX, 32) - ROUND2(ECX, EDX, EBP, EAX, EBX, 33) - ROUND2(EBX, ECX, EDX, EBP, EAX, 34) - ROUND2(EAX, EBX, ECX, EDX, EBP, 35) - ROUND2(EBP, EAX, EBX, ECX, EDX, 36) - ROUND2(EDX, EBP, EAX, EBX, ECX, 37) - ROUND2(ECX, EDX, EBP, EAX, EBX, 38) - ROUND2(EBX, ECX, EDX, EBP, EAX, 39) - - ROUND3(EAX, EBX, ECX, EDX, EBP, 40) - ROUND3(EBP, EAX, EBX, ECX, EDX, 41) - ROUND3(EDX, EBP, EAX, EBX, ECX, 42) - ROUND3(ECX, EDX, EBP, EAX, EBX, 43) - ROUND3(EBX, ECX, EDX, EBP, EAX, 44) - ROUND3(EAX, EBX, ECX, EDX, EBP, 45) - ROUND3(EBP, EAX, EBX, ECX, EDX, 46) - ROUND3(EDX, EBP, EAX, EBX, ECX, 47) - ROUND3(ECX, EDX, EBP, EAX, EBX, 48) - ROUND3(EBX, ECX, EDX, EBP, EAX, 49) - ROUND3(EAX, EBX, ECX, EDX, EBP, 50) - ROUND3(EBP, EAX, EBX, ECX, EDX, 51) - ROUND3(EDX, EBP, EAX, EBX, ECX, 52) - ROUND3(ECX, EDX, EBP, EAX, EBX, 53) - ROUND3(EBX, ECX, EDX, EBP, EAX, 54) - ROUND3(EAX, EBX, ECX, EDX, EBP, 55) - ROUND3(EBP, EAX, EBX, ECX, EDX, 56) - ROUND3(EDX, EBP, EAX, EBX, ECX, 57) - ROUND3(ECX, EDX, EBP, EAX, EBX, 58) - ROUND3(EBX, ECX, EDX, EBP, EAX, 59) - - ROUND4(EAX, EBX, ECX, EDX, EBP, 60) - ROUND4(EBP, EAX, EBX, ECX, EDX, 61) - ROUND4(EDX, EBP, EAX, EBX, ECX, 62) - ROUND4(ECX, EDX, EBP, EAX, EBX, 63) - ROUND4(EBX, ECX, EDX, EBP, EAX, 64) - ROUND4(EAX, EBX, ECX, EDX, EBP, 65) - ROUND4(EBP, EAX, EBX, ECX, EDX, 66) - ROUND4(EDX, EBP, EAX, EBX, ECX, 67) - ROUND4(ECX, EDX, EBP, EAX, EBX, 68) - ROUND4(EBX, ECX, EDX, EBP, EAX, 69) - ROUND4(EAX, EBX, ECX, EDX, EBP, 70) - ROUND4(EBP, EAX, EBX, ECX, EDX, 71) - ROUND4(EDX, EBP, EAX, EBX, ECX, 72) - ROUND4(ECX, EDX, EBP, EAX, EBX, 73) - ROUND4(EBX, ECX, EDX, EBP, EAX, 74) - ROUND4(EAX, EBX, ECX, EDX, EBP, 75) - ROUND4(EBP, EAX, EBX, ECX, EDX, 76) - ROUND4(EDX, EBP, EAX, EBX, ECX, 77) - ROUND4(ECX, EDX, EBP, EAX, EBX, 78) - ROUND4(EBX, ECX, EDX, EBP, EAX, 79) - - ADDL(R11L, EAX) - ADDL(R12L, EBX) - ADDL(R13L, ECX) - ADDL(R14L, EDX) - ADDL(R15L, EBP) - - ADDQ(Imm(64), RSI) - CMPQ(RSI, RDI) - JB(LabelRef("loop")) -} - -func end() { - Label("end") - Load(Param("dig"), RDI) - MOVL(EAX, Mem{Base: DI}.Offset(0*4)) - MOVL(EBX, Mem{Base: DI}.Offset(1*4)) - MOVL(ECX, Mem{Base: DI}.Offset(2*4)) - MOVL(EDX, Mem{Base: DI}.Offset(3*4)) - MOVL(EBP, Mem{Base: DI}.Offset(4*4)) - RET() -} - // This is the implementation using AVX2, BMI1 and BMI2. It is based on: // "SHA-1 implementation with Intel(R) AVX2 instruction set extensions" // From http://software.intel.com/en-us/articles diff --git a/crypto/sha1/_asm/sha1block_amd64_shani.go b/crypto/sha1/_asm/sha1block_amd64_shani.go new file mode 100644 index 00000000000..0a0160a823a --- /dev/null +++ b/crypto/sha1/_asm/sha1block_amd64_shani.go @@ -0,0 +1,164 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +// Implement the SHA-1 block function using the Intel(R) SHA extensions +// (SHA1RNDS4, SHA1NEXTE, SHA1MSG1, and SHA1MSG2). This implementation requires +// the AVX, SHA, SSE2, SSE4.1, and SSSE3 extensions. +// +// Reference: +// S. Gulley, et al, "New Instructions Supporting the Secure Hash +// Algorithm on Intel® Architecture Processors", July 2013 +// https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sha-extensions.html + +func blockSHANI() { + Implement("blockSHANI") + + digest := Load(Param("dig"), RDI) + data := Load(Param("p").Base(), RSI) + len := Load(Param("p").Len(), RDX) + + abcd := XMM() + msg0, msg1, msg2, msg3 := XMM(), XMM(), XMM(), XMM() + e0, e1 := XMM(), XMM() + shufMask := XMM() + + CMPQ(len, Imm(0)) + JEQ(LabelRef("done")) + ADDQ(data, len) + + stackPtr := GP64() + { + Comment("Allocate space on the stack for saving ABCD and E0, and align it to 16 bytes") + local := AllocLocal(32 + 16) + LEAQ(local.Offset(15), stackPtr) + tmp := GP64() + MOVQ(U64(15), tmp) + NOTQ(tmp) + ANDQ(tmp, stackPtr) + } + e0_save := Mem{Base: stackPtr} + abcd_save := Mem{Base: stackPtr}.Offset(16) + + Comment("Load initial hash state") + PINSRD(Imm(3), Mem{Base: digest}.Offset(16), e0) + VMOVDQU(Mem{Base: digest}, abcd) + PAND(upperMask(), e0) + PSHUFD(Imm(0x1b), abcd, abcd) + + VMOVDQA(flipMask(), shufMask) + + Label("loop") + + Comment("Save ABCD and E working values") + VMOVDQA(e0, e0_save) + VMOVDQA(abcd, abcd_save) + + Comment("Rounds 0-3") + VMOVDQU(Mem{Base: data}, msg0) + PSHUFB(shufMask, msg0) + PADDD(msg0, e0) + VMOVDQA(abcd, e1) + SHA1RNDS4(Imm(0), e0, abcd) + + Comment("Rounds 4-7") + VMOVDQU(Mem{Base: data}.Offset(16), msg1) + PSHUFB(shufMask, msg1) + SHA1NEXTE(msg1, e1) + VMOVDQA(abcd, e0) + SHA1RNDS4(Imm(0), e1, abcd) + SHA1MSG1(msg1, msg0) + + Comment("Rounds 8-11") + VMOVDQU(Mem{Base: data}.Offset(16*2), msg2) + PSHUFB(shufMask, msg2) + SHA1NEXTE(msg2, e0) + VMOVDQA(abcd, e1) + SHA1RNDS4(Imm(0), e0, abcd) + SHA1MSG1(msg2, msg1) + PXOR(msg2, msg0) + + // Rounds 12 through 67 use the same repeated pattern, with e0 and e1 ping-ponging + // back and forth, and each of the msg temporaries moving up one every four rounds. + msgs := []VecVirtual{msg3, msg0, msg1, msg2} + for i := range 14 { + Comment(fmt.Sprintf("Rounds %d-%d", 12+(i*4), 12+(i*4)+3)) + a, b := e1, e0 + if i == 0 { + VMOVDQU(Mem{Base: data}.Offset(16*3), msg3) + PSHUFB(shufMask, msg3) + } + if i%2 == 1 { + a, b = e0, e1 + } + imm := uint64((12 + i*4) / 20) + + SHA1NEXTE(msgs[i%4], a) + VMOVDQA(abcd, b) + SHA1MSG2(msgs[i%4], msgs[(1+i)%4]) + SHA1RNDS4(Imm(imm), a, abcd) + SHA1MSG1(msgs[i%4], msgs[(3+i)%4]) + PXOR(msgs[i%4], msgs[(2+i)%4]) + } + + Comment("Rounds 68-71") + SHA1NEXTE(msg1, e1) + VMOVDQA(abcd, e0) + SHA1MSG2(msg1, msg2) + SHA1RNDS4(Imm(3), e1, abcd) + PXOR(msg1, msg3) + + Comment("Rounds 72-75") + SHA1NEXTE(msg2, e0) + VMOVDQA(abcd, e1) + SHA1MSG2(msg2, msg3) + SHA1RNDS4(Imm(3), e0, abcd) + + Comment("Rounds 76-79") + SHA1NEXTE(msg3, e1) + VMOVDQA(abcd, e0) + SHA1RNDS4(Imm(3), e1, abcd) + + Comment("Add saved E and ABCD") + SHA1NEXTE(e0_save, e0) + PADDD(abcd_save, abcd) + + Comment("Check if we are done, if not return to the loop") + ADDQ(Imm(64), data) + CMPQ(data, len) + JNE(LabelRef("loop")) + + Comment("Write the hash state back to digest") + PSHUFD(Imm(0x1b), abcd, abcd) + VMOVDQU(abcd, Mem{Base: digest}) + PEXTRD(Imm(3), e0, Mem{Base: digest}.Offset(16)) + + Label("done") + RET() +} + +func flipMask() Mem { + mask := GLOBL("shuffle_mask", RODATA) + // 0x000102030405060708090a0b0c0d0e0f + DATA(0x00, U64(0x08090a0b0c0d0e0f)) + DATA(0x08, U64(0x0001020304050607)) + return mask +} + +func upperMask() Mem { + mask := GLOBL("upper_mask", RODATA) + // 0xFFFFFFFF000000000000000000000000 + DATA(0x00, U64(0x0000000000000000)) + DATA(0x08, U64(0xFFFFFFFF00000000)) + return mask +} diff --git a/crypto/sha1/fallback_test.go b/crypto/sha1/fallback_test.go deleted file mode 100644 index b869a939f60..00000000000 --- a/crypto/sha1/fallback_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build s390x && !purego - -package sha1 - -import ( - "fmt" - "io" - "testing" -) - -// Tests the fallback code path in case the optimized asm -// implementation cannot be used. -// See also TestBlockGeneric. -func TestGenericPath(t *testing.T) { - if !useAsm { - t.Skipf("assembly implementation unavailable") - } - useAsm = false - defer func() { useAsm = true }() - c := New() - in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" - gold := "0f58c2bb130f8182375f325c18342215255387e5" - if _, err := io.WriteString(c, in); err != nil { - t.Fatalf("could not write to c: %v", err) - } - out := fmt.Sprintf("%x", c.Sum(nil)) - if out != gold { - t.Fatalf("mismatch: got %s, wanted %s", out, gold) - } -} diff --git a/crypto/sha1/issue15617_test.go b/crypto/sha1/issue15617_test.go index dccb6796a96..956ff293941 100644 --- a/crypto/sha1/issue15617_test.go +++ b/crypto/sha1/issue15617_test.go @@ -7,21 +7,25 @@ package sha1_test import ( - "github.com/runZeroInc/excrypto/crypto/sha1" "syscall" "testing" + + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" + "github.com/runZeroInc/excrypto/crypto/sha1" ) func TestOutOfBoundsRead(t *testing.T) { - const pageSize = 4 << 10 - data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) - if err != nil { - panic(err) - } - if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil { - panic(err) - } - for i := 0; i < pageSize; i++ { - sha1.Sum(data[pageSize-i : pageSize]) - } + cryptotest.TestAllImplementations(t, "sha1", func(t *testing.T) { + const pageSize = 4 << 10 + data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) + if err != nil { + panic(err) + } + if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil { + panic(err) + } + for i := 0; i < pageSize; i++ { + sha1.Sum(data[pageSize-i : pageSize]) + } + }) } diff --git a/crypto/sha1/sha1.go b/crypto/sha1/sha1.go index e9b711f971e..f5307aa574d 100644 --- a/crypto/sha1/sha1.go +++ b/crypto/sha1/sha1.go @@ -10,10 +10,12 @@ package sha1 import ( "errors" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/internal/fips140only" "github.com/runZeroInc/excrypto/internal/byteorder" ) @@ -55,14 +57,14 @@ func (d *digest) MarshalBinary() ([]byte, error) { func (d *digest) AppendBinary(b []byte) ([]byte, error) { b = append(b, magic...) - b = byteorder.BeAppendUint32(b, d.h[0]) - b = byteorder.BeAppendUint32(b, d.h[1]) - b = byteorder.BeAppendUint32(b, d.h[2]) - b = byteorder.BeAppendUint32(b, d.h[3]) - b = byteorder.BeAppendUint32(b, d.h[4]) + b = byteorder.BEAppendUint32(b, d.h[0]) + b = byteorder.BEAppendUint32(b, d.h[1]) + b = byteorder.BEAppendUint32(b, d.h[2]) + b = byteorder.BEAppendUint32(b, d.h[3]) + b = byteorder.BEAppendUint32(b, d.h[4]) b = append(b, d.x[:d.nx]...) b = append(b, make([]byte, len(d.x)-d.nx)...) - b = byteorder.BeAppendUint64(b, d.len) + b = byteorder.BEAppendUint64(b, d.len) return b, nil } @@ -86,11 +88,16 @@ func (d *digest) UnmarshalBinary(b []byte) error { } func consumeUint64(b []byte) ([]byte, uint64) { - return b[8:], byteorder.BeUint64(b) + return b[8:], byteorder.BEUint64(b) } func consumeUint32(b []byte) ([]byte, uint32) { - return b[4:], byteorder.BeUint32(b) + return b[4:], byteorder.BEUint32(b) +} + +func (d *digest) Clone() (hash.Cloner, error) { + r := *d + return &r, nil } func (d *digest) Reset() { @@ -103,7 +110,7 @@ func (d *digest) Reset() { d.len = 0 } -// New512_224 returns a new [hash.Hash] computing the SHA1 checksum. The Hash +// New returns a new [hash.Hash] computing the SHA1 checksum. The Hash // also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. @@ -121,6 +128,9 @@ func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Write(p []byte) (nn int, err error) { + if fips140only.Enabled { + return 0, errors.New("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } boring.Unreachable() nn = len(p) d.len += uint64(nn) @@ -153,6 +163,10 @@ func (d *digest) Sum(in []byte) []byte { } func (d *digest) checkSum() [Size]byte { + if fips140only.Enabled { + panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } + len := d.len // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. var tmp [64 + 8]byte // padding + length buffer @@ -167,7 +181,7 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 padlen := tmp[:t+8] - byteorder.BePutUint64(padlen[t:], len) + byteorder.BEPutUint64(padlen[t:], len) d.Write(padlen) if d.nx != 0 { @@ -176,11 +190,11 @@ func (d *digest) checkSum() [Size]byte { var digest [Size]byte - byteorder.BePutUint32(digest[0:], d.h[0]) - byteorder.BePutUint32(digest[4:], d.h[1]) - byteorder.BePutUint32(digest[8:], d.h[2]) - byteorder.BePutUint32(digest[12:], d.h[3]) - byteorder.BePutUint32(digest[16:], d.h[4]) + byteorder.BEPutUint32(digest[0:], d.h[0]) + byteorder.BEPutUint32(digest[4:], d.h[1]) + byteorder.BEPutUint32(digest[8:], d.h[2]) + byteorder.BEPutUint32(digest[12:], d.h[3]) + byteorder.BEPutUint32(digest[16:], d.h[4]) return digest } @@ -193,6 +207,10 @@ func (d *digest) ConstantTimeSum(in []byte) []byte { } func (d *digest) constSum() [Size]byte { + if fips140only.Enabled { + panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } + var length [8]byte l := d.len << 3 for i := uint(0); i < 8; i++ { @@ -258,6 +276,9 @@ func Sum(data []byte) [Size]byte { if boring.Enabled { return boring.SHA1(data) } + if fips140only.Enabled { + panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } var d digest d.Reset() d.Write(data) diff --git a/crypto/sha1/sha1_test.go b/crypto/sha1/sha1_test.go index 5e84db2884a..290c4f42ac1 100644 --- a/crypto/sha1/sha1_test.go +++ b/crypto/sha1/sha1_test.go @@ -9,11 +9,10 @@ package sha1 import ( "bytes" "fmt" - "hash" "io" "testing" - "crypto/rand" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" @@ -62,6 +61,9 @@ var golden = []sha1Test{ } func TestGolden(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha1", testGolden) +} +func testGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] s := fmt.Sprintf("%x", Sum([]byte(g.in))) @@ -99,6 +101,9 @@ func TestGolden(t *testing.T) { } func TestGoldenMarshal(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha1", testGoldenMarshal) +} +func testGoldenMarshal(t *testing.T) { h := New() h2 := New() for _, g := range golden { @@ -158,23 +163,6 @@ func TestBlockSize(t *testing.T) { } } -// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. -func TestBlockGeneric(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't expose digest") - } - for i := 1; i < 30; i++ { // arbitrary factor - gen, asm := New().(*digest), New().(*digest) - buf := make([]byte, BlockSize*i) - rand.Read(buf) - blockGeneric(gen, buf) - block(asm, buf) - if *gen != *asm { - t.Errorf("For %#v block and blockGeneric resulted in different states", buf) - } - } -} - // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums @@ -212,8 +200,10 @@ func safeSum(h hash.Hash) (sum []byte, err error) { } func TestLargeHashes(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha1", testLargeHashes) +} +func testLargeHashes(t *testing.T) { for i, test := range largeUnmarshalTests { - h := New() if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { t.Errorf("test %d could not unmarshal: %v", i, err) @@ -233,9 +223,7 @@ func TestLargeHashes(t *testing.T) { } func TestAllocations(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } + cryptotest.SkipTestAllocations(t) in := []byte("hello, world!") out := make([]byte, 0, Size) h := New() @@ -250,7 +238,22 @@ func TestAllocations(t *testing.T) { } func TestSHA1Hash(t *testing.T) { - cryptotest.TestHash(t, New) + cryptotest.TestAllImplementations(t, "sha1", func(t *testing.T) { + cryptotest.TestHash(t, New) + }) +} + +func TestExtraMethods(t *testing.T) { + h := maybeCloner(New()) + cryptotest.NoExtraMethods(t, &h, "ConstantTimeSum", + "MarshalBinary", "UnmarshalBinary", "AppendBinary") +} + +func maybeCloner(h hash.Hash) any { + if c, ok := h.(hash.Cloner); ok { + return &c + } + return &h } var bench = New() diff --git a/crypto/sha1/sha1block_amd64.go b/crypto/sha1/sha1block_amd64.go index f9bd4b8cf12..5bf18b4e583 100644 --- a/crypto/sha1/sha1block_amd64.go +++ b/crypto/sha1/sha1block_amd64.go @@ -6,31 +6,41 @@ package sha1 -import "github.com/runZeroInc/excrypto/internal/cpu" +import ( + "github.com/runZeroInc/excrypto/crypto/internal/impl" + "github.com/runZeroInc/excrypto/internal/cpu" +) //go:noescape func blockAVX2(dig *digest, p []byte) //go:noescape -func blockAMD64(dig *digest, p []byte) +func blockSHANI(dig *digest, p []byte) -var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 +var useAVX2 = cpu.X86.HasAVX && cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 +var useSHANI = cpu.X86.HasAVX && cpu.X86.HasSHA && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 + +func init() { + impl.Register("sha1", "AVX2", &useAVX2) + impl.Register("sha1", "SHA-NI", &useSHANI) +} func block(dig *digest, p []byte) { - if useAVX2 && len(p) >= 256 { - // blockAVX2 calculates sha1 for 2 block per iteration - // it also interleaves precalculation for next block. - // So it may read up-to 192 bytes past end of p - // We may add checks inside blockAVX2, but this will - // just turn it into a copy of blockAMD64, - // so call it directly, instead. + if useSHANI { + blockSHANI(dig, p) + } else if useAVX2 && len(p) >= 256 { + // blockAVX2 calculates sha1 for 2 block per iteration and also + // interleaves precalculation for next block. So it may read up-to 192 + // bytes past end of p. We could add checks inside blockAVX2, but this + // would just turn it into a copy of the old pre-AVX2 amd64 SHA1 + // assembly implementation, so just call blockGeneric instead. safeLen := len(p) - 128 if safeLen%128 != 0 { safeLen -= 64 } blockAVX2(dig, p[:safeLen]) - blockAMD64(dig, p[safeLen:]) + blockGeneric(dig, p[safeLen:]) } else { - blockAMD64(dig, p) + blockGeneric(dig, p) } } diff --git a/crypto/sha1/sha1block_amd64.s b/crypto/sha1/sha1block_amd64.s index 9c7aa146774..4e0c43ee4e1 100644 --- a/crypto/sha1/sha1block_amd64.s +++ b/crypto/sha1/sha1block_amd64.s @@ -4,1278 +4,6 @@ #include "textflag.h" -// func blockAMD64(dig *digest, p []byte) -TEXT ·blockAMD64(SB), NOSPLIT, $64-32 - MOVQ dig+0(FP), BP - MOVQ p_base+8(FP), SI - MOVQ p_len+16(FP), DX - SHRQ $0x06, DX - SHLQ $0x06, DX - LEAQ (SI)(DX*1), DI - MOVL (BP), AX - MOVL 4(BP), BX - MOVL 8(BP), CX - MOVL 12(BP), DX - MOVL 16(BP), BP - CMPQ SI, DI - JEQ end - -loop: - MOVL AX, R11 - MOVL BX, R12 - MOVL CX, R13 - MOVL DX, R14 - MOVL BP, R15 - MOVL (SI), R10 - BSWAPL R10 - MOVL R10, (SP) - MOVL DX, R9 - XORL CX, R9 - ANDL BX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BP)(R10*1), BP - ADDL R8, BP - MOVL 4(SI), R10 - BSWAPL R10 - MOVL R10, 4(SP) - MOVL CX, R9 - XORL BX, R9 - ANDL AX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1518500249(DX)(R10*1), DX - ADDL R8, DX - MOVL 8(SI), R10 - BSWAPL R10 - MOVL R10, 8(SP) - MOVL BX, R9 - XORL AX, R9 - ANDL BP, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1518500249(CX)(R10*1), CX - ADDL R8, CX - MOVL 12(SI), R10 - BSWAPL R10 - MOVL R10, 12(SP) - MOVL AX, R9 - XORL BP, R9 - ANDL DX, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BX)(R10*1), BX - ADDL R8, BX - MOVL 16(SI), R10 - BSWAPL R10 - MOVL R10, 16(SP) - MOVL BP, R9 - XORL DX, R9 - ANDL CX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1518500249(AX)(R10*1), AX - ADDL R8, AX - MOVL 20(SI), R10 - BSWAPL R10 - MOVL R10, 20(SP) - MOVL DX, R9 - XORL CX, R9 - ANDL BX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BP)(R10*1), BP - ADDL R8, BP - MOVL 24(SI), R10 - BSWAPL R10 - MOVL R10, 24(SP) - MOVL CX, R9 - XORL BX, R9 - ANDL AX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1518500249(DX)(R10*1), DX - ADDL R8, DX - MOVL 28(SI), R10 - BSWAPL R10 - MOVL R10, 28(SP) - MOVL BX, R9 - XORL AX, R9 - ANDL BP, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1518500249(CX)(R10*1), CX - ADDL R8, CX - MOVL 32(SI), R10 - BSWAPL R10 - MOVL R10, 32(SP) - MOVL AX, R9 - XORL BP, R9 - ANDL DX, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BX)(R10*1), BX - ADDL R8, BX - MOVL 36(SI), R10 - BSWAPL R10 - MOVL R10, 36(SP) - MOVL BP, R9 - XORL DX, R9 - ANDL CX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1518500249(AX)(R10*1), AX - ADDL R8, AX - MOVL 40(SI), R10 - BSWAPL R10 - MOVL R10, 40(SP) - MOVL DX, R9 - XORL CX, R9 - ANDL BX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BP)(R10*1), BP - ADDL R8, BP - MOVL 44(SI), R10 - BSWAPL R10 - MOVL R10, 44(SP) - MOVL CX, R9 - XORL BX, R9 - ANDL AX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1518500249(DX)(R10*1), DX - ADDL R8, DX - MOVL 48(SI), R10 - BSWAPL R10 - MOVL R10, 48(SP) - MOVL BX, R9 - XORL AX, R9 - ANDL BP, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1518500249(CX)(R10*1), CX - ADDL R8, CX - MOVL 52(SI), R10 - BSWAPL R10 - MOVL R10, 52(SP) - MOVL AX, R9 - XORL BP, R9 - ANDL DX, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BX)(R10*1), BX - ADDL R8, BX - MOVL 56(SI), R10 - BSWAPL R10 - MOVL R10, 56(SP) - MOVL BP, R9 - XORL DX, R9 - ANDL CX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1518500249(AX)(R10*1), AX - ADDL R8, AX - MOVL 60(SI), R10 - BSWAPL R10 - MOVL R10, 60(SP) - MOVL DX, R9 - XORL CX, R9 - ANDL BX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BP)(R10*1), BP - ADDL R8, BP - MOVL (SP), R10 - XORL 52(SP), R10 - XORL 32(SP), R10 - XORL 8(SP), R10 - ROLL $0x01, R10 - MOVL R10, (SP) - MOVL CX, R9 - XORL BX, R9 - ANDL AX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1518500249(DX)(R10*1), DX - ADDL R8, DX - MOVL 4(SP), R10 - XORL 56(SP), R10 - XORL 36(SP), R10 - XORL 12(SP), R10 - ROLL $0x01, R10 - MOVL R10, 4(SP) - MOVL BX, R9 - XORL AX, R9 - ANDL BP, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1518500249(CX)(R10*1), CX - ADDL R8, CX - MOVL 8(SP), R10 - XORL 60(SP), R10 - XORL 40(SP), R10 - XORL 16(SP), R10 - ROLL $0x01, R10 - MOVL R10, 8(SP) - MOVL AX, R9 - XORL BP, R9 - ANDL DX, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1518500249(BX)(R10*1), BX - ADDL R8, BX - MOVL 12(SP), R10 - XORL (SP), R10 - XORL 44(SP), R10 - XORL 20(SP), R10 - ROLL $0x01, R10 - MOVL R10, 12(SP) - MOVL BP, R9 - XORL DX, R9 - ANDL CX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1518500249(AX)(R10*1), AX - ADDL R8, AX - MOVL 16(SP), R10 - XORL 4(SP), R10 - XORL 48(SP), R10 - XORL 24(SP), R10 - ROLL $0x01, R10 - MOVL R10, 16(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BP)(R10*1), BP - ADDL R8, BP - MOVL 20(SP), R10 - XORL 8(SP), R10 - XORL 52(SP), R10 - XORL 28(SP), R10 - ROLL $0x01, R10 - MOVL R10, 20(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1859775393(DX)(R10*1), DX - ADDL R8, DX - MOVL 24(SP), R10 - XORL 12(SP), R10 - XORL 56(SP), R10 - XORL 32(SP), R10 - ROLL $0x01, R10 - MOVL R10, 24(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1859775393(CX)(R10*1), CX - ADDL R8, CX - MOVL 28(SP), R10 - XORL 16(SP), R10 - XORL 60(SP), R10 - XORL 36(SP), R10 - ROLL $0x01, R10 - MOVL R10, 28(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BX)(R10*1), BX - ADDL R8, BX - MOVL 32(SP), R10 - XORL 20(SP), R10 - XORL (SP), R10 - XORL 40(SP), R10 - ROLL $0x01, R10 - MOVL R10, 32(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1859775393(AX)(R10*1), AX - ADDL R8, AX - MOVL 36(SP), R10 - XORL 24(SP), R10 - XORL 4(SP), R10 - XORL 44(SP), R10 - ROLL $0x01, R10 - MOVL R10, 36(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BP)(R10*1), BP - ADDL R8, BP - MOVL 40(SP), R10 - XORL 28(SP), R10 - XORL 8(SP), R10 - XORL 48(SP), R10 - ROLL $0x01, R10 - MOVL R10, 40(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1859775393(DX)(R10*1), DX - ADDL R8, DX - MOVL 44(SP), R10 - XORL 32(SP), R10 - XORL 12(SP), R10 - XORL 52(SP), R10 - ROLL $0x01, R10 - MOVL R10, 44(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1859775393(CX)(R10*1), CX - ADDL R8, CX - MOVL 48(SP), R10 - XORL 36(SP), R10 - XORL 16(SP), R10 - XORL 56(SP), R10 - ROLL $0x01, R10 - MOVL R10, 48(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BX)(R10*1), BX - ADDL R8, BX - MOVL 52(SP), R10 - XORL 40(SP), R10 - XORL 20(SP), R10 - XORL 60(SP), R10 - ROLL $0x01, R10 - MOVL R10, 52(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1859775393(AX)(R10*1), AX - ADDL R8, AX - MOVL 56(SP), R10 - XORL 44(SP), R10 - XORL 24(SP), R10 - XORL (SP), R10 - ROLL $0x01, R10 - MOVL R10, 56(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BP)(R10*1), BP - ADDL R8, BP - MOVL 60(SP), R10 - XORL 48(SP), R10 - XORL 28(SP), R10 - XORL 4(SP), R10 - ROLL $0x01, R10 - MOVL R10, 60(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1859775393(DX)(R10*1), DX - ADDL R8, DX - MOVL (SP), R10 - XORL 52(SP), R10 - XORL 32(SP), R10 - XORL 8(SP), R10 - ROLL $0x01, R10 - MOVL R10, (SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1859775393(CX)(R10*1), CX - ADDL R8, CX - MOVL 4(SP), R10 - XORL 56(SP), R10 - XORL 36(SP), R10 - XORL 12(SP), R10 - ROLL $0x01, R10 - MOVL R10, 4(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BX)(R10*1), BX - ADDL R8, BX - MOVL 8(SP), R10 - XORL 60(SP), R10 - XORL 40(SP), R10 - XORL 16(SP), R10 - ROLL $0x01, R10 - MOVL R10, 8(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1859775393(AX)(R10*1), AX - ADDL R8, AX - MOVL 12(SP), R10 - XORL (SP), R10 - XORL 44(SP), R10 - XORL 20(SP), R10 - ROLL $0x01, R10 - MOVL R10, 12(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BP)(R10*1), BP - ADDL R8, BP - MOVL 16(SP), R10 - XORL 4(SP), R10 - XORL 48(SP), R10 - XORL 24(SP), R10 - ROLL $0x01, R10 - MOVL R10, 16(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 1859775393(DX)(R10*1), DX - ADDL R8, DX - MOVL 20(SP), R10 - XORL 8(SP), R10 - XORL 52(SP), R10 - XORL 28(SP), R10 - ROLL $0x01, R10 - MOVL R10, 20(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 1859775393(CX)(R10*1), CX - ADDL R8, CX - MOVL 24(SP), R10 - XORL 12(SP), R10 - XORL 56(SP), R10 - XORL 32(SP), R10 - ROLL $0x01, R10 - MOVL R10, 24(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 1859775393(BX)(R10*1), BX - ADDL R8, BX - MOVL 28(SP), R10 - XORL 16(SP), R10 - XORL 60(SP), R10 - XORL 36(SP), R10 - ROLL $0x01, R10 - MOVL R10, 28(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 1859775393(AX)(R10*1), AX - ADDL R8, AX - MOVL 32(SP), R10 - XORL 20(SP), R10 - XORL (SP), R10 - XORL 40(SP), R10 - ROLL $0x01, R10 - MOVL R10, 32(SP) - MOVL BX, R8 - ORL CX, R8 - ANDL DX, R8 - MOVL BX, R9 - ANDL CX, R9 - ORL R8, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BP)(R10*1), BP - ADDL R8, BP - MOVL 36(SP), R10 - XORL 24(SP), R10 - XORL 4(SP), R10 - XORL 44(SP), R10 - ROLL $0x01, R10 - MOVL R10, 36(SP) - MOVL AX, R8 - ORL BX, R8 - ANDL CX, R8 - MOVL AX, R9 - ANDL BX, R9 - ORL R8, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 2400959708(DX)(R10*1), DX - ADDL R8, DX - MOVL 40(SP), R10 - XORL 28(SP), R10 - XORL 8(SP), R10 - XORL 48(SP), R10 - ROLL $0x01, R10 - MOVL R10, 40(SP) - MOVL BP, R8 - ORL AX, R8 - ANDL BX, R8 - MOVL BP, R9 - ANDL AX, R9 - ORL R8, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 2400959708(CX)(R10*1), CX - ADDL R8, CX - MOVL 44(SP), R10 - XORL 32(SP), R10 - XORL 12(SP), R10 - XORL 52(SP), R10 - ROLL $0x01, R10 - MOVL R10, 44(SP) - MOVL DX, R8 - ORL BP, R8 - ANDL AX, R8 - MOVL DX, R9 - ANDL BP, R9 - ORL R8, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BX)(R10*1), BX - ADDL R8, BX - MOVL 48(SP), R10 - XORL 36(SP), R10 - XORL 16(SP), R10 - XORL 56(SP), R10 - ROLL $0x01, R10 - MOVL R10, 48(SP) - MOVL CX, R8 - ORL DX, R8 - ANDL BP, R8 - MOVL CX, R9 - ANDL DX, R9 - ORL R8, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 2400959708(AX)(R10*1), AX - ADDL R8, AX - MOVL 52(SP), R10 - XORL 40(SP), R10 - XORL 20(SP), R10 - XORL 60(SP), R10 - ROLL $0x01, R10 - MOVL R10, 52(SP) - MOVL BX, R8 - ORL CX, R8 - ANDL DX, R8 - MOVL BX, R9 - ANDL CX, R9 - ORL R8, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BP)(R10*1), BP - ADDL R8, BP - MOVL 56(SP), R10 - XORL 44(SP), R10 - XORL 24(SP), R10 - XORL (SP), R10 - ROLL $0x01, R10 - MOVL R10, 56(SP) - MOVL AX, R8 - ORL BX, R8 - ANDL CX, R8 - MOVL AX, R9 - ANDL BX, R9 - ORL R8, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 2400959708(DX)(R10*1), DX - ADDL R8, DX - MOVL 60(SP), R10 - XORL 48(SP), R10 - XORL 28(SP), R10 - XORL 4(SP), R10 - ROLL $0x01, R10 - MOVL R10, 60(SP) - MOVL BP, R8 - ORL AX, R8 - ANDL BX, R8 - MOVL BP, R9 - ANDL AX, R9 - ORL R8, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 2400959708(CX)(R10*1), CX - ADDL R8, CX - MOVL (SP), R10 - XORL 52(SP), R10 - XORL 32(SP), R10 - XORL 8(SP), R10 - ROLL $0x01, R10 - MOVL R10, (SP) - MOVL DX, R8 - ORL BP, R8 - ANDL AX, R8 - MOVL DX, R9 - ANDL BP, R9 - ORL R8, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BX)(R10*1), BX - ADDL R8, BX - MOVL 4(SP), R10 - XORL 56(SP), R10 - XORL 36(SP), R10 - XORL 12(SP), R10 - ROLL $0x01, R10 - MOVL R10, 4(SP) - MOVL CX, R8 - ORL DX, R8 - ANDL BP, R8 - MOVL CX, R9 - ANDL DX, R9 - ORL R8, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 2400959708(AX)(R10*1), AX - ADDL R8, AX - MOVL 8(SP), R10 - XORL 60(SP), R10 - XORL 40(SP), R10 - XORL 16(SP), R10 - ROLL $0x01, R10 - MOVL R10, 8(SP) - MOVL BX, R8 - ORL CX, R8 - ANDL DX, R8 - MOVL BX, R9 - ANDL CX, R9 - ORL R8, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BP)(R10*1), BP - ADDL R8, BP - MOVL 12(SP), R10 - XORL (SP), R10 - XORL 44(SP), R10 - XORL 20(SP), R10 - ROLL $0x01, R10 - MOVL R10, 12(SP) - MOVL AX, R8 - ORL BX, R8 - ANDL CX, R8 - MOVL AX, R9 - ANDL BX, R9 - ORL R8, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 2400959708(DX)(R10*1), DX - ADDL R8, DX - MOVL 16(SP), R10 - XORL 4(SP), R10 - XORL 48(SP), R10 - XORL 24(SP), R10 - ROLL $0x01, R10 - MOVL R10, 16(SP) - MOVL BP, R8 - ORL AX, R8 - ANDL BX, R8 - MOVL BP, R9 - ANDL AX, R9 - ORL R8, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 2400959708(CX)(R10*1), CX - ADDL R8, CX - MOVL 20(SP), R10 - XORL 8(SP), R10 - XORL 52(SP), R10 - XORL 28(SP), R10 - ROLL $0x01, R10 - MOVL R10, 20(SP) - MOVL DX, R8 - ORL BP, R8 - ANDL AX, R8 - MOVL DX, R9 - ANDL BP, R9 - ORL R8, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BX)(R10*1), BX - ADDL R8, BX - MOVL 24(SP), R10 - XORL 12(SP), R10 - XORL 56(SP), R10 - XORL 32(SP), R10 - ROLL $0x01, R10 - MOVL R10, 24(SP) - MOVL CX, R8 - ORL DX, R8 - ANDL BP, R8 - MOVL CX, R9 - ANDL DX, R9 - ORL R8, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 2400959708(AX)(R10*1), AX - ADDL R8, AX - MOVL 28(SP), R10 - XORL 16(SP), R10 - XORL 60(SP), R10 - XORL 36(SP), R10 - ROLL $0x01, R10 - MOVL R10, 28(SP) - MOVL BX, R8 - ORL CX, R8 - ANDL DX, R8 - MOVL BX, R9 - ANDL CX, R9 - ORL R8, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BP)(R10*1), BP - ADDL R8, BP - MOVL 32(SP), R10 - XORL 20(SP), R10 - XORL (SP), R10 - XORL 40(SP), R10 - ROLL $0x01, R10 - MOVL R10, 32(SP) - MOVL AX, R8 - ORL BX, R8 - ANDL CX, R8 - MOVL AX, R9 - ANDL BX, R9 - ORL R8, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 2400959708(DX)(R10*1), DX - ADDL R8, DX - MOVL 36(SP), R10 - XORL 24(SP), R10 - XORL 4(SP), R10 - XORL 44(SP), R10 - ROLL $0x01, R10 - MOVL R10, 36(SP) - MOVL BP, R8 - ORL AX, R8 - ANDL BX, R8 - MOVL BP, R9 - ANDL AX, R9 - ORL R8, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 2400959708(CX)(R10*1), CX - ADDL R8, CX - MOVL 40(SP), R10 - XORL 28(SP), R10 - XORL 8(SP), R10 - XORL 48(SP), R10 - ROLL $0x01, R10 - MOVL R10, 40(SP) - MOVL DX, R8 - ORL BP, R8 - ANDL AX, R8 - MOVL DX, R9 - ANDL BP, R9 - ORL R8, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 2400959708(BX)(R10*1), BX - ADDL R8, BX - MOVL 44(SP), R10 - XORL 32(SP), R10 - XORL 12(SP), R10 - XORL 52(SP), R10 - ROLL $0x01, R10 - MOVL R10, 44(SP) - MOVL CX, R8 - ORL DX, R8 - ANDL BP, R8 - MOVL CX, R9 - ANDL DX, R9 - ORL R8, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 2400959708(AX)(R10*1), AX - ADDL R8, AX - MOVL 48(SP), R10 - XORL 36(SP), R10 - XORL 16(SP), R10 - XORL 56(SP), R10 - ROLL $0x01, R10 - MOVL R10, 48(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BP)(R10*1), BP - ADDL R8, BP - MOVL 52(SP), R10 - XORL 40(SP), R10 - XORL 20(SP), R10 - XORL 60(SP), R10 - ROLL $0x01, R10 - MOVL R10, 52(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 3395469782(DX)(R10*1), DX - ADDL R8, DX - MOVL 56(SP), R10 - XORL 44(SP), R10 - XORL 24(SP), R10 - XORL (SP), R10 - ROLL $0x01, R10 - MOVL R10, 56(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 3395469782(CX)(R10*1), CX - ADDL R8, CX - MOVL 60(SP), R10 - XORL 48(SP), R10 - XORL 28(SP), R10 - XORL 4(SP), R10 - ROLL $0x01, R10 - MOVL R10, 60(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BX)(R10*1), BX - ADDL R8, BX - MOVL (SP), R10 - XORL 52(SP), R10 - XORL 32(SP), R10 - XORL 8(SP), R10 - ROLL $0x01, R10 - MOVL R10, (SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 3395469782(AX)(R10*1), AX - ADDL R8, AX - MOVL 4(SP), R10 - XORL 56(SP), R10 - XORL 36(SP), R10 - XORL 12(SP), R10 - ROLL $0x01, R10 - MOVL R10, 4(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BP)(R10*1), BP - ADDL R8, BP - MOVL 8(SP), R10 - XORL 60(SP), R10 - XORL 40(SP), R10 - XORL 16(SP), R10 - ROLL $0x01, R10 - MOVL R10, 8(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 3395469782(DX)(R10*1), DX - ADDL R8, DX - MOVL 12(SP), R10 - XORL (SP), R10 - XORL 44(SP), R10 - XORL 20(SP), R10 - ROLL $0x01, R10 - MOVL R10, 12(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 3395469782(CX)(R10*1), CX - ADDL R8, CX - MOVL 16(SP), R10 - XORL 4(SP), R10 - XORL 48(SP), R10 - XORL 24(SP), R10 - ROLL $0x01, R10 - MOVL R10, 16(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BX)(R10*1), BX - ADDL R8, BX - MOVL 20(SP), R10 - XORL 8(SP), R10 - XORL 52(SP), R10 - XORL 28(SP), R10 - ROLL $0x01, R10 - MOVL R10, 20(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 3395469782(AX)(R10*1), AX - ADDL R8, AX - MOVL 24(SP), R10 - XORL 12(SP), R10 - XORL 56(SP), R10 - XORL 32(SP), R10 - ROLL $0x01, R10 - MOVL R10, 24(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BP)(R10*1), BP - ADDL R8, BP - MOVL 28(SP), R10 - XORL 16(SP), R10 - XORL 60(SP), R10 - XORL 36(SP), R10 - ROLL $0x01, R10 - MOVL R10, 28(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 3395469782(DX)(R10*1), DX - ADDL R8, DX - MOVL 32(SP), R10 - XORL 20(SP), R10 - XORL (SP), R10 - XORL 40(SP), R10 - ROLL $0x01, R10 - MOVL R10, 32(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 3395469782(CX)(R10*1), CX - ADDL R8, CX - MOVL 36(SP), R10 - XORL 24(SP), R10 - XORL 4(SP), R10 - XORL 44(SP), R10 - ROLL $0x01, R10 - MOVL R10, 36(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BX)(R10*1), BX - ADDL R8, BX - MOVL 40(SP), R10 - XORL 28(SP), R10 - XORL 8(SP), R10 - XORL 48(SP), R10 - ROLL $0x01, R10 - MOVL R10, 40(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 3395469782(AX)(R10*1), AX - ADDL R8, AX - MOVL 44(SP), R10 - XORL 32(SP), R10 - XORL 12(SP), R10 - XORL 52(SP), R10 - ROLL $0x01, R10 - MOVL R10, 44(SP) - MOVL BX, R9 - XORL CX, R9 - XORL DX, R9 - ROLL $0x1e, BX - ADDL R9, BP - MOVL AX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BP)(R10*1), BP - ADDL R8, BP - MOVL 48(SP), R10 - XORL 36(SP), R10 - XORL 16(SP), R10 - XORL 56(SP), R10 - ROLL $0x01, R10 - MOVL R10, 48(SP) - MOVL AX, R9 - XORL BX, R9 - XORL CX, R9 - ROLL $0x1e, AX - ADDL R9, DX - MOVL BP, R8 - ROLL $0x05, R8 - LEAL 3395469782(DX)(R10*1), DX - ADDL R8, DX - MOVL 52(SP), R10 - XORL 40(SP), R10 - XORL 20(SP), R10 - XORL 60(SP), R10 - ROLL $0x01, R10 - MOVL R10, 52(SP) - MOVL BP, R9 - XORL AX, R9 - XORL BX, R9 - ROLL $0x1e, BP - ADDL R9, CX - MOVL DX, R8 - ROLL $0x05, R8 - LEAL 3395469782(CX)(R10*1), CX - ADDL R8, CX - MOVL 56(SP), R10 - XORL 44(SP), R10 - XORL 24(SP), R10 - XORL (SP), R10 - ROLL $0x01, R10 - MOVL R10, 56(SP) - MOVL DX, R9 - XORL BP, R9 - XORL AX, R9 - ROLL $0x1e, DX - ADDL R9, BX - MOVL CX, R8 - ROLL $0x05, R8 - LEAL 3395469782(BX)(R10*1), BX - ADDL R8, BX - MOVL 60(SP), R10 - XORL 48(SP), R10 - XORL 28(SP), R10 - XORL 4(SP), R10 - ROLL $0x01, R10 - MOVL R10, 60(SP) - MOVL CX, R9 - XORL DX, R9 - XORL BP, R9 - ROLL $0x1e, CX - ADDL R9, AX - MOVL BX, R8 - ROLL $0x05, R8 - LEAL 3395469782(AX)(R10*1), AX - ADDL R8, AX - ADDL R11, AX - ADDL R12, BX - ADDL R13, CX - ADDL R14, DX - ADDL R15, BP - ADDQ $0x40, SI - CMPQ SI, DI - JB loop - -end: - MOVQ dig+0(FP), DI - MOVL AX, (DI) - MOVL BX, 4(DI) - MOVL CX, 8(DI) - MOVL DX, 12(DI) - MOVL BP, 16(DI) - RET - // func blockAVX2(dig *digest, p []byte) // Requires: AVX, AVX2, BMI, BMI2, CMOV TEXT ·blockAVX2(SB), $1408-32 @@ -3049,3 +1777,212 @@ DATA BSWAP_SHUFB_CTL<>+20(SB)/4, $0x04050607 DATA BSWAP_SHUFB_CTL<>+24(SB)/4, $0x08090a0b DATA BSWAP_SHUFB_CTL<>+28(SB)/4, $0x0c0d0e0f GLOBL BSWAP_SHUFB_CTL<>(SB), RODATA, $32 + +// func blockSHANI(dig *digest, p []byte) +// Requires: AVX, SHA, SSE2, SSE4.1, SSSE3 +TEXT ·blockSHANI(SB), $48-32 + MOVQ dig+0(FP), DI + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + CMPQ DX, $0x00 + JEQ done + ADDQ SI, DX + + // Allocate space on the stack for saving ABCD and E0, and align it to 16 bytes + LEAQ 15(SP), AX + MOVQ $0x000000000000000f, CX + NOTQ CX + ANDQ CX, AX + + // Load initial hash state + PINSRD $0x03, 16(DI), X5 + VMOVDQU (DI), X0 + PAND upper_mask<>+0(SB), X5 + PSHUFD $0x1b, X0, X0 + VMOVDQA shuffle_mask<>+0(SB), X7 + +loop: + // Save ABCD and E working values + VMOVDQA X5, (AX) + VMOVDQA X0, 16(AX) + + // Rounds 0-3 + VMOVDQU (SI), X1 + PSHUFB X7, X1 + PADDD X1, X5 + VMOVDQA X0, X6 + SHA1RNDS4 $0x00, X5, X0 + + // Rounds 4-7 + VMOVDQU 16(SI), X2 + PSHUFB X7, X2 + SHA1NEXTE X2, X6 + VMOVDQA X0, X5 + SHA1RNDS4 $0x00, X6, X0 + SHA1MSG1 X2, X1 + + // Rounds 8-11 + VMOVDQU 32(SI), X3 + PSHUFB X7, X3 + SHA1NEXTE X3, X5 + VMOVDQA X0, X6 + SHA1RNDS4 $0x00, X5, X0 + SHA1MSG1 X3, X2 + PXOR X3, X1 + + // Rounds 12-15 + VMOVDQU 48(SI), X4 + PSHUFB X7, X4 + SHA1NEXTE X4, X6 + VMOVDQA X0, X5 + SHA1MSG2 X4, X1 + SHA1RNDS4 $0x00, X6, X0 + SHA1MSG1 X4, X3 + PXOR X4, X2 + + // Rounds 16-19 + SHA1NEXTE X1, X5 + VMOVDQA X0, X6 + SHA1MSG2 X1, X2 + SHA1RNDS4 $0x00, X5, X0 + SHA1MSG1 X1, X4 + PXOR X1, X3 + + // Rounds 20-23 + SHA1NEXTE X2, X6 + VMOVDQA X0, X5 + SHA1MSG2 X2, X3 + SHA1RNDS4 $0x01, X6, X0 + SHA1MSG1 X2, X1 + PXOR X2, X4 + + // Rounds 24-27 + SHA1NEXTE X3, X5 + VMOVDQA X0, X6 + SHA1MSG2 X3, X4 + SHA1RNDS4 $0x01, X5, X0 + SHA1MSG1 X3, X2 + PXOR X3, X1 + + // Rounds 28-31 + SHA1NEXTE X4, X6 + VMOVDQA X0, X5 + SHA1MSG2 X4, X1 + SHA1RNDS4 $0x01, X6, X0 + SHA1MSG1 X4, X3 + PXOR X4, X2 + + // Rounds 32-35 + SHA1NEXTE X1, X5 + VMOVDQA X0, X6 + SHA1MSG2 X1, X2 + SHA1RNDS4 $0x01, X5, X0 + SHA1MSG1 X1, X4 + PXOR X1, X3 + + // Rounds 36-39 + SHA1NEXTE X2, X6 + VMOVDQA X0, X5 + SHA1MSG2 X2, X3 + SHA1RNDS4 $0x01, X6, X0 + SHA1MSG1 X2, X1 + PXOR X2, X4 + + // Rounds 40-43 + SHA1NEXTE X3, X5 + VMOVDQA X0, X6 + SHA1MSG2 X3, X4 + SHA1RNDS4 $0x02, X5, X0 + SHA1MSG1 X3, X2 + PXOR X3, X1 + + // Rounds 44-47 + SHA1NEXTE X4, X6 + VMOVDQA X0, X5 + SHA1MSG2 X4, X1 + SHA1RNDS4 $0x02, X6, X0 + SHA1MSG1 X4, X3 + PXOR X4, X2 + + // Rounds 48-51 + SHA1NEXTE X1, X5 + VMOVDQA X0, X6 + SHA1MSG2 X1, X2 + SHA1RNDS4 $0x02, X5, X0 + SHA1MSG1 X1, X4 + PXOR X1, X3 + + // Rounds 52-55 + SHA1NEXTE X2, X6 + VMOVDQA X0, X5 + SHA1MSG2 X2, X3 + SHA1RNDS4 $0x02, X6, X0 + SHA1MSG1 X2, X1 + PXOR X2, X4 + + // Rounds 56-59 + SHA1NEXTE X3, X5 + VMOVDQA X0, X6 + SHA1MSG2 X3, X4 + SHA1RNDS4 $0x02, X5, X0 + SHA1MSG1 X3, X2 + PXOR X3, X1 + + // Rounds 60-63 + SHA1NEXTE X4, X6 + VMOVDQA X0, X5 + SHA1MSG2 X4, X1 + SHA1RNDS4 $0x03, X6, X0 + SHA1MSG1 X4, X3 + PXOR X4, X2 + + // Rounds 64-67 + SHA1NEXTE X1, X5 + VMOVDQA X0, X6 + SHA1MSG2 X1, X2 + SHA1RNDS4 $0x03, X5, X0 + SHA1MSG1 X1, X4 + PXOR X1, X3 + + // Rounds 68-71 + SHA1NEXTE X2, X6 + VMOVDQA X0, X5 + SHA1MSG2 X2, X3 + SHA1RNDS4 $0x03, X6, X0 + PXOR X2, X4 + + // Rounds 72-75 + SHA1NEXTE X3, X5 + VMOVDQA X0, X6 + SHA1MSG2 X3, X4 + SHA1RNDS4 $0x03, X5, X0 + + // Rounds 76-79 + SHA1NEXTE X4, X6 + VMOVDQA X0, X5 + SHA1RNDS4 $0x03, X6, X0 + + // Add saved E and ABCD + SHA1NEXTE (AX), X5 + PADDD 16(AX), X0 + + // Check if we are done, if not return to the loop + ADDQ $0x40, SI + CMPQ SI, DX + JNE loop + + // Write the hash state back to digest + PSHUFD $0x1b, X0, X0 + VMOVDQU X0, (DI) + PEXTRD $0x03, X5, 16(DI) + +done: + RET + +DATA upper_mask<>+0(SB)/8, $0x0000000000000000 +DATA upper_mask<>+8(SB)/8, $0xffffffff00000000 +GLOBL upper_mask<>(SB), RODATA, $16 + +DATA shuffle_mask<>+0(SB)/8, $0x08090a0b0c0d0e0f +DATA shuffle_mask<>+8(SB)/8, $0x0001020304050607 +GLOBL shuffle_mask<>(SB), RODATA, $16 diff --git a/crypto/sha1/sha1block_arm64.go b/crypto/sha1/sha1block_arm64.go index 26beb2c9900..1475d88fb29 100644 --- a/crypto/sha1/sha1block_arm64.go +++ b/crypto/sha1/sha1block_arm64.go @@ -6,7 +6,16 @@ package sha1 -import "github.com/runZeroInc/excrypto/internal/cpu" +import ( + "github.com/runZeroInc/excrypto/crypto/internal/impl" + "github.com/runZeroInc/excrypto/internal/cpu" +) + +var useSHA1 = cpu.ARM64.HasSHA1 + +func init() { + impl.Register("sha1", "Armv8.0", &useSHA1) +} var k = []uint32{ 0x5A827999, @@ -19,10 +28,10 @@ var k = []uint32{ func sha1block(h []uint32, p []byte, k []uint32) func block(dig *digest, p []byte) { - if !cpu.ARM64.HasSHA1 { - blockGeneric(dig, p) - } else { + if useSHA1 { h := dig.h[:] sha1block(h, p, k) + } else { + blockGeneric(dig, p) } } diff --git a/crypto/sha1/sha1block_decl.go b/crypto/sha1/sha1block_decl.go index 46f41a1cc26..887d8cad01f 100644 --- a/crypto/sha1/sha1block_decl.go +++ b/crypto/sha1/sha1block_decl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (386 || arm || loong64 || s390x) && !purego +//go:build (386 || arm || loong64) && !purego package sha1 diff --git a/crypto/sha1/sha1block_loong64.s b/crypto/sha1/sha1block_loong64.s index 7e9d6e09339..b76b193ad0e 100644 --- a/crypto/sha1/sha1block_loong64.s +++ b/crypto/sha1/sha1block_loong64.s @@ -29,7 +29,7 @@ #define LOAD1(index) \ MOVW (index*4)(R5), REGTMP3; \ - WORD $0x3a73; \ // REVB2W REGTMP3, REGTMP3 to big-endian + REVB2W REGTMP3, REGTMP3; \ MOVW REGTMP3, (index*4)(R3) #define LOAD(index) \ diff --git a/crypto/sha1/sha1block_s390x.go b/crypto/sha1/sha1block_s390x.go index 7677ebef19f..6ddcf9569e7 100644 --- a/crypto/sha1/sha1block_s390x.go +++ b/crypto/sha1/sha1block_s390x.go @@ -6,6 +6,26 @@ package sha1 -import "github.com/runZeroInc/excrypto/internal/cpu" +import ( + "github.com/runZeroInc/excrypto/crypto/internal/impl" + "github.com/runZeroInc/excrypto/internal/cpu" +) -var useAsm = cpu.S390X.HasSHA1 +var useSHA1 = cpu.S390X.HasSHA1 + +func init() { + // CP Assist for Cryptographic Functions (CPACF) + // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf + impl.Register("sha1", "CPACF", &useSHA1) +} + +//go:noescape +func blockS390X(dig *digest, p []byte) + +func block(dig *digest, p []byte) { + if useSHA1 { + blockS390X(dig, p) + } else { + blockGeneric(dig, p) + } +} diff --git a/crypto/sha1/sha1block_s390x.s b/crypto/sha1/sha1block_s390x.s index 7a2f4e39c40..3ddc9b586a0 100644 --- a/crypto/sha1/sha1block_s390x.s +++ b/crypto/sha1/sha1block_s390x.s @@ -6,17 +6,12 @@ #include "textflag.h" -// func block(dig *digest, p []byte) -TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 - MOVBZ ·useAsm(SB), R4 +// func blockS390X(dig *digest, p []byte) +TEXT ·blockS390X(SB), NOSPLIT|NOFRAME, $0-32 LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) MOVBZ $1, R0 // SHA-1 function code - CMPBEQ R4, $0, generic loop: KIMD R0, R2 // compute intermediate message digest (KIMD) BVS loop // continue if interrupted RET - -generic: - BR ·blockGeneric(SB) diff --git a/crypto/sha256/_asm/go.mod b/crypto/sha256/_asm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/sha256/_asm/go.sum b/crypto/sha256/_asm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/sha256/example_test.go b/crypto/sha256/example_test.go index a377e943ff2..dc7c8f3870d 100644 --- a/crypto/sha256/example_test.go +++ b/crypto/sha256/example_test.go @@ -6,10 +6,11 @@ package sha256_test import ( "fmt" - "github.com/runZeroInc/excrypto/crypto/sha256" "io" "log" "os" + + "github.com/runZeroInc/excrypto/crypto/sha256" ) func ExampleSum256() { diff --git a/crypto/sha256/fallback_test.go b/crypto/sha256/fallback_test.go deleted file mode 100644 index ceef3cc9222..00000000000 --- a/crypto/sha256/fallback_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build s390x && !purego - -package sha256 - -import ( - "fmt" - "io" - "testing" -) - -// Tests the fallback code path in case the optimized asm -// implementation cannot be used. -// See also TestBlockGeneric. -func TestGenericPath(t *testing.T) { - if useAsm == false { - t.Skipf("assembly implementation unavailable") - } - useAsm = false - defer func() { useAsm = true }() - c := New() - in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" - gold := "e93d84ec2b22383123be9f713697fb25" + - "338c86e2f7d8d1ddc2d89d332dd9d76c" - if _, err := io.WriteString(c, in); err != nil { - t.Fatalf("could not write to c: %v", err) - } - out := fmt.Sprintf("%x", c.Sum(nil)) - if out != gold { - t.Fatalf("mismatch: got %s, wanted %s", out, gold) - } -} diff --git a/crypto/sha256/sha256.go b/crypto/sha256/sha256.go index 037bfddd61f..a2f7fa95d69 100644 --- a/crypto/sha256/sha256.go +++ b/crypto/sha256/sha256.go @@ -7,12 +7,11 @@ package sha256 import ( - "errors" - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" - "github.com/runZeroInc/excrypto/internal/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha256" ) func init() { @@ -29,119 +28,6 @@ const Size224 = 28 // The blocksize of SHA256 and SHA224 in bytes. const BlockSize = 64 -const ( - chunk = 64 - init0 = 0x6A09E667 - init1 = 0xBB67AE85 - init2 = 0x3C6EF372 - init3 = 0xA54FF53A - init4 = 0x510E527F - init5 = 0x9B05688C - init6 = 0x1F83D9AB - init7 = 0x5BE0CD19 - init0_224 = 0xC1059ED8 - init1_224 = 0x367CD507 - init2_224 = 0x3070DD17 - init3_224 = 0xF70E5939 - init4_224 = 0xFFC00B31 - init5_224 = 0x68581511 - init6_224 = 0x64F98FA7 - init7_224 = 0xBEFA4FA4 -) - -// digest represents the partial evaluation of a checksum. -type digest struct { - h [8]uint32 - x [chunk]byte - nx int - len uint64 - is224 bool // mark if this digest is SHA-224 -} - -const ( - magic224 = "sha\x02" - magic256 = "sha\x03" - marshaledSize = len(magic256) + 8*4 + chunk + 8 -) - -func (d *digest) MarshalBinary() ([]byte, error) { - return d.AppendBinary(make([]byte, 0, marshaledSize)) -} - -func (d *digest) AppendBinary(b []byte) ([]byte, error) { - if d.is224 { - b = append(b, magic224...) - } else { - b = append(b, magic256...) - } - b = byteorder.BeAppendUint32(b, d.h[0]) - b = byteorder.BeAppendUint32(b, d.h[1]) - b = byteorder.BeAppendUint32(b, d.h[2]) - b = byteorder.BeAppendUint32(b, d.h[3]) - b = byteorder.BeAppendUint32(b, d.h[4]) - b = byteorder.BeAppendUint32(b, d.h[5]) - b = byteorder.BeAppendUint32(b, d.h[6]) - b = byteorder.BeAppendUint32(b, d.h[7]) - b = append(b, d.x[:d.nx]...) - b = append(b, make([]byte, len(d.x)-d.nx)...) - b = byteorder.BeAppendUint64(b, d.len) - return b, nil -} - -func (d *digest) UnmarshalBinary(b []byte) error { - if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) { - return errors.New("crypto/sha256: invalid hash state identifier") - } - if len(b) != marshaledSize { - return errors.New("crypto/sha256: invalid hash state size") - } - b = b[len(magic224):] - b, d.h[0] = consumeUint32(b) - b, d.h[1] = consumeUint32(b) - b, d.h[2] = consumeUint32(b) - b, d.h[3] = consumeUint32(b) - b, d.h[4] = consumeUint32(b) - b, d.h[5] = consumeUint32(b) - b, d.h[6] = consumeUint32(b) - b, d.h[7] = consumeUint32(b) - b = b[copy(d.x[:], b):] - b, d.len = consumeUint64(b) - d.nx = int(d.len % chunk) - return nil -} - -func consumeUint64(b []byte) ([]byte, uint64) { - return b[8:], byteorder.BeUint64(b) -} - -func consumeUint32(b []byte) ([]byte, uint32) { - return b[4:], byteorder.BeUint32(b) -} - -func (d *digest) Reset() { - if !d.is224 { - d.h[0] = init0 - d.h[1] = init1 - d.h[2] = init2 - d.h[3] = init3 - d.h[4] = init4 - d.h[5] = init5 - d.h[6] = init6 - d.h[7] = init7 - } else { - d.h[0] = init0_224 - d.h[1] = init1_224 - d.h[2] = init2_224 - d.h[3] = init3_224 - d.h[4] = init4_224 - d.h[5] = init5_224 - d.h[6] = init6_224 - d.h[7] = init7_224 - } - d.nx = 0 - d.len = 0 -} - // New returns a new [hash.Hash] computing the SHA256 checksum. The Hash // also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal @@ -150,9 +36,7 @@ func New() hash.Hash { if boring.Enabled { return boring.NewSHA256() } - d := new(digest) - d.Reset() - return d + return sha256.New() } // New224 returns a new [hash.Hash] computing the SHA224 checksum. The Hash @@ -163,92 +47,7 @@ func New224() hash.Hash { if boring.Enabled { return boring.NewSHA224() } - d := new(digest) - d.is224 = true - d.Reset() - return d -} - -func (d *digest) Size() int { - if !d.is224 { - return Size - } - return Size224 -} - -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Write(p []byte) (nn int, err error) { - boring.Unreachable() - nn = len(p) - d.len += uint64(nn) - if d.nx > 0 { - n := copy(d.x[d.nx:], p) - d.nx += n - if d.nx == chunk { - block(d, d.x[:]) - d.nx = 0 - } - p = p[n:] - } - if len(p) >= chunk { - n := len(p) &^ (chunk - 1) - block(d, p[:n]) - p = p[n:] - } - if len(p) > 0 { - d.nx = copy(d.x[:], p) - } - return -} - -func (d *digest) Sum(in []byte) []byte { - boring.Unreachable() - // Make a copy of d so that caller can keep writing and summing. - d0 := *d - hash := d0.checkSum() - if d0.is224 { - return append(in, hash[:Size224]...) - } - return append(in, hash[:]...) -} - -func (d *digest) checkSum() [Size]byte { - len := d.len - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. - var tmp [64 + 8]byte // padding + length buffer - tmp[0] = 0x80 - var t uint64 - if len%64 < 56 { - t = 56 - len%64 - } else { - t = 64 + 56 - len%64 - } - - // Length in bits. - len <<= 3 - padlen := tmp[:t+8] - byteorder.BePutUint64(padlen[t+0:], len) - d.Write(padlen) - - if d.nx != 0 { - panic("d.nx != 0") - } - - var digest [Size]byte - - byteorder.BePutUint32(digest[0:], d.h[0]) - byteorder.BePutUint32(digest[4:], d.h[1]) - byteorder.BePutUint32(digest[8:], d.h[2]) - byteorder.BePutUint32(digest[12:], d.h[3]) - byteorder.BePutUint32(digest[16:], d.h[4]) - byteorder.BePutUint32(digest[20:], d.h[5]) - byteorder.BePutUint32(digest[24:], d.h[6]) - if !d.is224 { - byteorder.BePutUint32(digest[28:], d.h[7]) - } - - return digest + return sha256.New224() } // Sum256 returns the SHA256 checksum of the data. @@ -256,10 +55,11 @@ func Sum256(data []byte) [Size]byte { if boring.Enabled { return boring.SHA256(data) } - var d digest - d.Reset() - d.Write(data) - return d.checkSum() + h := New() + h.Write(data) + var sum [Size]byte + h.Sum(sum[:0]) + return sum } // Sum224 returns the SHA224 checksum of the data. @@ -267,11 +67,9 @@ func Sum224(data []byte) [Size224]byte { if boring.Enabled { return boring.SHA224(data) } - var d digest - d.is224 = true - d.Reset() - d.Write(data) - sum := d.checkSum() - ap := (*[Size224]byte)(sum[:]) - return *ap + h := New224() + h.Write(data) + var sum [Size224]byte + h.Sum(sum[:0]) + return sum } diff --git a/crypto/sha256/sha256_test.go b/crypto/sha256/sha256_test.go index d510b83d4cf..01dbff2b0fd 100644 --- a/crypto/sha256/sha256_test.go +++ b/crypto/sha256/sha256_test.go @@ -8,16 +8,14 @@ package sha256 import ( "bytes" + "encoding" "fmt" - "hash" "io" "testing" - "crypto/rand" + "github.com/runZeroInc/excrypto/hash" - "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" - "github.com/runZeroInc/excrypto/encoding" ) type sha256Test struct { @@ -95,8 +93,11 @@ var golden224 = []sha256Test{ } func TestGolden(t *testing.T) { - for i := 0; i < len(golden); i++ { - g := golden[i] + cryptotest.TestAllImplementations(t, "sha256", testGolden) +} + +func testGolden(t *testing.T) { + for _, g := range golden { s := fmt.Sprintf("%x", Sum256([]byte(g.in))) if s != g.out { t.Fatalf("Sum256 function: sha256(%s) = %s want %s", g.in, s, g.out) @@ -117,8 +118,7 @@ func TestGolden(t *testing.T) { c.Reset() } } - for i := 0; i < len(golden224); i++ { - g := golden224[i] + for _, g := range golden224 { s := fmt.Sprintf("%x", Sum224([]byte(g.in))) if s != g.out { t.Fatalf("Sum224 function: sha224(%s) = %s want %s", g.in, s, g.out) @@ -142,6 +142,10 @@ func TestGolden(t *testing.T) { } func TestGoldenMarshal(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha256", testGoldenMarshal) +} + +func testGoldenMarshal(t *testing.T) { tests := []struct { name string newHash func() hash.Hash @@ -198,6 +202,56 @@ func TestGoldenMarshal(t *testing.T) { } } +func TestLarge(t *testing.T) { + const N = 10000 + const offsets = 4 + ok := "4c207598af7a20db0e3334dd044399a40e467cb81b37f7ba05a4f76dcbd8fd59" // sha256sum of "0123456789" * 1000 + block := make([]byte, N+offsets) + c := New() + for offset := 0; offset < offsets; offset++ { + for i := 0; i < N; i++ { + block[offset+i] = '0' + byte(i%10) + } + for blockSize := 10; blockSize <= N; blockSize *= 10 { + blocks := N / blockSize + b := block[offset : offset+blockSize] + c.Reset() + for i := 0; i < blocks; i++ { + c.Write(b) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != ok { + t.Fatalf("sha256 TestLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok) + } + } + } +} + +func TestExtraLarge(t *testing.T) { + const N = 100000 + const offsets = 4 + ok := "aca9e593cc629cbaa94cd5a07dc029424aad93e5129e5d11f8dcd2f139c16cc0" // sha256sum of "0123456789" * 10000 + block := make([]byte, N+offsets) + c := New() + for offset := 0; offset < offsets; offset++ { + for i := 0; i < N; i++ { + block[offset+i] = '0' + byte(i%10) + } + for blockSize := 10; blockSize <= N; blockSize *= 10 { + blocks := N / blockSize + b := block[offset : offset+blockSize] + c.Reset() + for i := 0; i < blocks; i++ { + c.Write(b) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != ok { + t.Fatalf("sha256 TestExtraLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok) + } + } + } +} + func TestMarshalTypeMismatch(t *testing.T) { h1 := New() h2 := New224() @@ -230,21 +284,6 @@ func TestBlockSize(t *testing.T) { } } -// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. -func TestBlockGeneric(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't expose digest") - } - gen, asm := New().(*digest), New().(*digest) - buf := make([]byte, BlockSize*20) // arbitrary factor - rand.Read(buf) - blockGeneric(gen, buf) - block(asm, buf) - if *gen != *asm { - t.Error("block and blockGeneric resulted in different states") - } -} - // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums @@ -309,19 +348,28 @@ func TestLargeHashes(t *testing.T) { } func TestAllocations(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } - in := []byte("hello, world!") - out := make([]byte, 0, Size) - h := New() - n := int(testing.AllocsPerRun(10, func() { - h.Reset() - h.Write(in) - out = h.Sum(out[:0]) - })) - if n > 0 { - t.Errorf("allocs = %d, want 0", n) + cryptotest.SkipTestAllocations(t) + if n := testing.AllocsPerRun(10, func() { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + + { + h := New() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + { + h := New224() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + + Sum256(in) + Sum224(in) + }); n > 0 { + t.Errorf("allocs = %v, want 0", n) } } @@ -335,31 +383,58 @@ func TestCgo(t *testing.T) { // The scan (if any) should be limited to the [16]byte. d := new(cgoData) d.Ptr = d + _ = d.Ptr // for unusedwrite check h := New() h.Write(d.Data[:]) h.Sum(nil) } -func TestSHA256Hash(t *testing.T) { +func TestHash(t *testing.T) { t.Run("SHA-224", func(t *testing.T) { - cryptotest.TestHash(t, New224) + cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) { + cryptotest.TestHash(t, New224) + }) }) t.Run("SHA-256", func(t *testing.T) { - cryptotest.TestHash(t, New) + cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) { + cryptotest.TestHash(t, New) + }) }) } +func TestExtraMethods(t *testing.T) { + t.Run("SHA-224", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) { + h := maybeCloner(New224()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) + t.Run("SHA-256", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) { + h := maybeCloner(New()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) +} + +func maybeCloner(h hash.Hash) any { + if c, ok := h.(hash.Cloner); ok { + return &c + } + return &h +} + var bench = New() -var buf = make([]byte, 8192) func benchmarkSize(b *testing.B, size int) { + buf := make([]byte, size) sum := make([]byte, bench.Size()) b.Run("New", func(b *testing.B) { b.ReportAllocs() b.SetBytes(int64(size)) for i := 0; i < b.N; i++ { bench.Reset() - bench.Write(buf[:size]) + bench.Write(buf) bench.Sum(sum[:0]) } }) @@ -367,14 +442,14 @@ func benchmarkSize(b *testing.B, size int) { b.ReportAllocs() b.SetBytes(int64(size)) for i := 0; i < b.N; i++ { - Sum224(buf[:size]) + Sum224(buf) } }) b.Run("Sum256", func(b *testing.B) { b.ReportAllocs() b.SetBytes(int64(size)) for i := 0; i < b.N; i++ { - Sum256(buf[:size]) + Sum256(buf) } }) } @@ -390,3 +465,11 @@ func BenchmarkHash1K(b *testing.B) { func BenchmarkHash8K(b *testing.B) { benchmarkSize(b, 8192) } + +func BenchmarkHash256K(b *testing.B) { + benchmarkSize(b, 256*1024) +} + +func BenchmarkHash1M(b *testing.B) { + benchmarkSize(b, 1024*1024) +} diff --git a/crypto/sha256/sha256block_amd64.go b/crypto/sha256/sha256block_amd64.go deleted file mode 100644 index 3cf081cff26..00000000000 --- a/crypto/sha256/sha256block_amd64.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha256 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 -var useSHA = useAVX2 && cpu.X86.HasSHA diff --git a/crypto/sha256/sha256block_amd64.s b/crypto/sha256/sha256block_amd64.s deleted file mode 100644 index 700a4eff97e..00000000000 --- a/crypto/sha256/sha256block_amd64.s +++ /dev/null @@ -1,4973 +0,0 @@ -// Code generated by command: go run sha256block_amd64_asm.go -out ../sha256block_amd64.s -pkg sha256. DO NOT EDIT. - -//go:build !purego - -#include "textflag.h" - -// func block(dig *digest, p []byte) -// Requires: AVX, AVX2, BMI2, SHA, SSE2, SSE4.1, SSSE3 -TEXT ·block(SB), $536-32 - CMPB ·useSHA+0(SB), $0x01 - JE sha_ni - CMPB ·useAVX2+0(SB), $0x01 - JE avx2 - MOVQ p_base+8(FP), SI - MOVQ p_len+16(FP), DX - SHRQ $0x06, DX - SHLQ $0x06, DX - LEAQ (SI)(DX*1), DI - MOVQ DI, 256(SP) - CMPQ SI, DI - JEQ end - MOVQ dig+0(FP), BP - MOVL (BP), R8 - MOVL 4(BP), R9 - MOVL 8(BP), R10 - MOVL 12(BP), R11 - MOVL 16(BP), R12 - MOVL 20(BP), R13 - MOVL 24(BP), R14 - MOVL 28(BP), R15 - -loop: - MOVQ SP, BP - MOVL (SI), AX - BSWAPL AX - MOVL AX, (BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0x428a2f98, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 4(SI), AX - BSWAPL AX - MOVL AX, 4(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0x71374491, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 8(SI), AX - BSWAPL AX - MOVL AX, 8(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0xb5c0fbcf, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 12(SI), AX - BSWAPL AX - MOVL AX, 12(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0xe9b5dba5, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 16(SI), AX - BSWAPL AX - MOVL AX, 16(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x3956c25b, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 20(SI), AX - BSWAPL AX - MOVL AX, 20(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0x59f111f1, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 24(SI), AX - BSWAPL AX - MOVL AX, 24(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x923f82a4, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 28(SI), AX - BSWAPL AX - MOVL AX, 28(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0xab1c5ed5, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 32(SI), AX - BSWAPL AX - MOVL AX, 32(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0xd807aa98, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 36(SI), AX - BSWAPL AX - MOVL AX, 36(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0x12835b01, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 40(SI), AX - BSWAPL AX - MOVL AX, 40(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0x243185be, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 44(SI), AX - BSWAPL AX - MOVL AX, 44(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0x550c7dc3, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 48(SI), AX - BSWAPL AX - MOVL AX, 48(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x72be5d74, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 52(SI), AX - BSWAPL AX - MOVL AX, 52(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0x80deb1fe, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 56(SI), AX - BSWAPL AX - MOVL AX, 56(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x9bdc06a7, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 60(SI), AX - BSWAPL AX - MOVL AX, 60(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0xc19bf174, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 56(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 4(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 36(BP), AX - XORL CX, BX - XORL DX, BX - ADDL (BP), BX - ADDL BX, AX - MOVL AX, 64(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0xe49b69c1, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 60(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 8(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 40(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 4(BP), BX - ADDL BX, AX - MOVL AX, 68(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0xefbe4786, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 64(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 12(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 44(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 8(BP), BX - ADDL BX, AX - MOVL AX, 72(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0x0fc19dc6, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 68(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 16(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 48(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 12(BP), BX - ADDL BX, AX - MOVL AX, 76(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0x240ca1cc, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 72(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 20(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 52(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 16(BP), BX - ADDL BX, AX - MOVL AX, 80(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x2de92c6f, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 76(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 24(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 56(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 20(BP), BX - ADDL BX, AX - MOVL AX, 84(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0x4a7484aa, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 80(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 28(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 60(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 24(BP), BX - ADDL BX, AX - MOVL AX, 88(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x5cb0a9dc, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 84(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 32(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 64(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 28(BP), BX - ADDL BX, AX - MOVL AX, 92(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0x76f988da, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 88(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 36(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 68(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 32(BP), BX - ADDL BX, AX - MOVL AX, 96(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0x983e5152, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 92(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 40(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 72(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 36(BP), BX - ADDL BX, AX - MOVL AX, 100(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0xa831c66d, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 96(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 44(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 76(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 40(BP), BX - ADDL BX, AX - MOVL AX, 104(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0xb00327c8, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 100(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 48(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 80(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 44(BP), BX - ADDL BX, AX - MOVL AX, 108(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0xbf597fc7, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 104(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 52(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 84(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 48(BP), BX - ADDL BX, AX - MOVL AX, 112(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0xc6e00bf3, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 108(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 56(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 88(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 52(BP), BX - ADDL BX, AX - MOVL AX, 116(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0xd5a79147, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 112(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 60(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 92(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 56(BP), BX - ADDL BX, AX - MOVL AX, 120(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x06ca6351, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 116(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 64(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 96(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 60(BP), BX - ADDL BX, AX - MOVL AX, 124(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0x14292967, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 120(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 68(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 100(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 64(BP), BX - ADDL BX, AX - MOVL AX, 128(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0x27b70a85, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 124(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 72(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 104(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 68(BP), BX - ADDL BX, AX - MOVL AX, 132(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0x2e1b2138, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 128(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 76(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 108(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 72(BP), BX - ADDL BX, AX - MOVL AX, 136(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0x4d2c6dfc, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 132(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 80(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 112(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 76(BP), BX - ADDL BX, AX - MOVL AX, 140(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0x53380d13, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 136(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 84(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 116(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 80(BP), BX - ADDL BX, AX - MOVL AX, 144(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x650a7354, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 140(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 88(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 120(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 84(BP), BX - ADDL BX, AX - MOVL AX, 148(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0x766a0abb, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 144(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 92(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 124(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 88(BP), BX - ADDL BX, AX - MOVL AX, 152(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x81c2c92e, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 148(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 96(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 128(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 92(BP), BX - ADDL BX, AX - MOVL AX, 156(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0x92722c85, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 152(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 100(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 132(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 96(BP), BX - ADDL BX, AX - MOVL AX, 160(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0xa2bfe8a1, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 156(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 104(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 136(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 100(BP), BX - ADDL BX, AX - MOVL AX, 164(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0xa81a664b, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 160(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 108(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 140(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 104(BP), BX - ADDL BX, AX - MOVL AX, 168(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0xc24b8b70, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 164(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 112(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 144(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 108(BP), BX - ADDL BX, AX - MOVL AX, 172(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0xc76c51a3, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 168(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 116(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 148(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 112(BP), BX - ADDL BX, AX - MOVL AX, 176(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0xd192e819, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 172(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 120(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 152(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 116(BP), BX - ADDL BX, AX - MOVL AX, 180(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0xd6990624, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 176(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 124(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 156(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 120(BP), BX - ADDL BX, AX - MOVL AX, 184(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0xf40e3585, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 180(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 128(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 160(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 124(BP), BX - ADDL BX, AX - MOVL AX, 188(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0x106aa070, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 184(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 132(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 164(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 128(BP), BX - ADDL BX, AX - MOVL AX, 192(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0x19a4c116, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 188(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 136(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 168(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 132(BP), BX - ADDL BX, AX - MOVL AX, 196(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0x1e376c08, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 192(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 140(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 172(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 136(BP), BX - ADDL BX, AX - MOVL AX, 200(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0x2748774c, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 196(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 144(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 176(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 140(BP), BX - ADDL BX, AX - MOVL AX, 204(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0x34b0bcb5, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 200(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 148(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 180(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 144(BP), BX - ADDL BX, AX - MOVL AX, 208(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x391c0cb3, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 204(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 152(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 184(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 148(BP), BX - ADDL BX, AX - MOVL AX, 212(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0x4ed8aa4a, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 208(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 156(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 188(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 152(BP), BX - ADDL BX, AX - MOVL AX, 216(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0x5b9cca4f, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 212(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 160(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 192(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 156(BP), BX - ADDL BX, AX - MOVL AX, 220(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0x682e6ff3, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVL 216(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 164(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 196(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 160(BP), BX - ADDL BX, AX - MOVL AX, 224(BP) - ADDL AX, R15 - MOVL R12, AX - ADDL $0x748f82ee, R15 - MOVL R12, CX - RORL $0x06, AX - MOVL R12, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R12, CX - RORL $0x19, DX - ANDL R13, CX - XORL AX, DX - MOVL R12, AX - NOTL AX - ADDL DX, R15 - ANDL R14, AX - XORL CX, AX - ADDL R15, AX - MOVL R8, DI - MOVL R10, BX - RORL $0x02, DI - MOVL R8, DX - ANDL R9, BX - RORL $0x0d, DX - MOVL R8, CX - ANDL R10, CX - XORL DX, DI - XORL CX, BX - MOVL R8, DX - MOVL R9, CX - RORL $0x16, DX - ANDL R8, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R15 - ADDL AX, R11 - ADDL AX, R15 - MOVL 220(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 168(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 200(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 164(BP), BX - ADDL BX, AX - MOVL AX, 228(BP) - ADDL AX, R14 - MOVL R11, AX - ADDL $0x78a5636f, R14 - MOVL R11, CX - RORL $0x06, AX - MOVL R11, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R11, CX - RORL $0x19, DX - ANDL R12, CX - XORL AX, DX - MOVL R11, AX - NOTL AX - ADDL DX, R14 - ANDL R13, AX - XORL CX, AX - ADDL R14, AX - MOVL R15, DI - MOVL R9, BX - RORL $0x02, DI - MOVL R15, DX - ANDL R8, BX - RORL $0x0d, DX - MOVL R15, CX - ANDL R9, CX - XORL DX, DI - XORL CX, BX - MOVL R15, DX - MOVL R8, CX - RORL $0x16, DX - ANDL R15, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R14 - ADDL AX, R10 - ADDL AX, R14 - MOVL 224(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 172(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 204(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 168(BP), BX - ADDL BX, AX - MOVL AX, 232(BP) - ADDL AX, R13 - MOVL R10, AX - ADDL $0x84c87814, R13 - MOVL R10, CX - RORL $0x06, AX - MOVL R10, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R10, CX - RORL $0x19, DX - ANDL R11, CX - XORL AX, DX - MOVL R10, AX - NOTL AX - ADDL DX, R13 - ANDL R12, AX - XORL CX, AX - ADDL R13, AX - MOVL R14, DI - MOVL R8, BX - RORL $0x02, DI - MOVL R14, DX - ANDL R15, BX - RORL $0x0d, DX - MOVL R14, CX - ANDL R8, CX - XORL DX, DI - XORL CX, BX - MOVL R14, DX - MOVL R15, CX - RORL $0x16, DX - ANDL R14, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R13 - ADDL AX, R9 - ADDL AX, R13 - MOVL 228(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 176(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 208(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 172(BP), BX - ADDL BX, AX - MOVL AX, 236(BP) - ADDL AX, R12 - MOVL R9, AX - ADDL $0x8cc70208, R12 - MOVL R9, CX - RORL $0x06, AX - MOVL R9, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R9, CX - RORL $0x19, DX - ANDL R10, CX - XORL AX, DX - MOVL R9, AX - NOTL AX - ADDL DX, R12 - ANDL R11, AX - XORL CX, AX - ADDL R12, AX - MOVL R13, DI - MOVL R15, BX - RORL $0x02, DI - MOVL R13, DX - ANDL R14, BX - RORL $0x0d, DX - MOVL R13, CX - ANDL R15, CX - XORL DX, DI - XORL CX, BX - MOVL R13, DX - MOVL R14, CX - RORL $0x16, DX - ANDL R13, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R12 - ADDL AX, R8 - ADDL AX, R12 - MOVL 232(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 180(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 212(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 176(BP), BX - ADDL BX, AX - MOVL AX, 240(BP) - ADDL AX, R11 - MOVL R8, AX - ADDL $0x90befffa, R11 - MOVL R8, CX - RORL $0x06, AX - MOVL R8, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R8, CX - RORL $0x19, DX - ANDL R9, CX - XORL AX, DX - MOVL R8, AX - NOTL AX - ADDL DX, R11 - ANDL R10, AX - XORL CX, AX - ADDL R11, AX - MOVL R12, DI - MOVL R14, BX - RORL $0x02, DI - MOVL R12, DX - ANDL R13, BX - RORL $0x0d, DX - MOVL R12, CX - ANDL R14, CX - XORL DX, DI - XORL CX, BX - MOVL R12, DX - MOVL R13, CX - RORL $0x16, DX - ANDL R12, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R11 - ADDL AX, R15 - ADDL AX, R11 - MOVL 236(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 184(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 216(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 180(BP), BX - ADDL BX, AX - MOVL AX, 244(BP) - ADDL AX, R10 - MOVL R15, AX - ADDL $0xa4506ceb, R10 - MOVL R15, CX - RORL $0x06, AX - MOVL R15, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R15, CX - RORL $0x19, DX - ANDL R8, CX - XORL AX, DX - MOVL R15, AX - NOTL AX - ADDL DX, R10 - ANDL R9, AX - XORL CX, AX - ADDL R10, AX - MOVL R11, DI - MOVL R13, BX - RORL $0x02, DI - MOVL R11, DX - ANDL R12, BX - RORL $0x0d, DX - MOVL R11, CX - ANDL R13, CX - XORL DX, DI - XORL CX, BX - MOVL R11, DX - MOVL R12, CX - RORL $0x16, DX - ANDL R11, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R10 - ADDL AX, R14 - ADDL AX, R10 - MOVL 240(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 188(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 220(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 184(BP), BX - ADDL BX, AX - MOVL AX, 248(BP) - ADDL AX, R9 - MOVL R14, AX - ADDL $0xbef9a3f7, R9 - MOVL R14, CX - RORL $0x06, AX - MOVL R14, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R14, CX - RORL $0x19, DX - ANDL R15, CX - XORL AX, DX - MOVL R14, AX - NOTL AX - ADDL DX, R9 - ANDL R8, AX - XORL CX, AX - ADDL R9, AX - MOVL R10, DI - MOVL R12, BX - RORL $0x02, DI - MOVL R10, DX - ANDL R11, BX - RORL $0x0d, DX - MOVL R10, CX - ANDL R12, CX - XORL DX, DI - XORL CX, BX - MOVL R10, DX - MOVL R11, CX - RORL $0x16, DX - ANDL R10, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R9 - ADDL AX, R13 - ADDL AX, R9 - MOVL 244(BP), AX - MOVL AX, CX - RORL $0x11, AX - MOVL CX, DX - RORL $0x13, CX - SHRL $0x0a, DX - MOVL 192(BP), BX - XORL CX, AX - MOVL BX, CX - XORL DX, AX - RORL $0x07, BX - MOVL CX, DX - SHRL $0x03, DX - RORL $0x12, CX - ADDL 224(BP), AX - XORL CX, BX - XORL DX, BX - ADDL 188(BP), BX - ADDL BX, AX - MOVL AX, 252(BP) - ADDL AX, R8 - MOVL R13, AX - ADDL $0xc67178f2, R8 - MOVL R13, CX - RORL $0x06, AX - MOVL R13, DX - RORL $0x0b, CX - XORL CX, AX - MOVL R13, CX - RORL $0x19, DX - ANDL R14, CX - XORL AX, DX - MOVL R13, AX - NOTL AX - ADDL DX, R8 - ANDL R15, AX - XORL CX, AX - ADDL R8, AX - MOVL R9, DI - MOVL R11, BX - RORL $0x02, DI - MOVL R9, DX - ANDL R10, BX - RORL $0x0d, DX - MOVL R9, CX - ANDL R11, CX - XORL DX, DI - XORL CX, BX - MOVL R9, DX - MOVL R10, CX - RORL $0x16, DX - ANDL R9, CX - XORL CX, BX - XORL DX, DI - ADDL DI, BX - MOVL BX, R8 - ADDL AX, R12 - ADDL AX, R8 - MOVQ dig+0(FP), BP - ADDL (BP), R8 - MOVL R8, (BP) - ADDL 4(BP), R9 - MOVL R9, 4(BP) - ADDL 8(BP), R10 - MOVL R10, 8(BP) - ADDL 12(BP), R11 - MOVL R11, 12(BP) - ADDL 16(BP), R12 - MOVL R12, 16(BP) - ADDL 20(BP), R13 - MOVL R13, 20(BP) - ADDL 24(BP), R14 - MOVL R14, 24(BP) - ADDL 28(BP), R15 - MOVL R15, 28(BP) - ADDQ $0x40, SI - CMPQ SI, 256(SP) - JB loop - -end: - RET - -avx2: - MOVQ dig+0(FP), SI - MOVQ p_base+8(FP), DI - MOVQ p_len+16(FP), DX - LEAQ -64(DI)(DX*1), DX - MOVQ DX, 512(SP) - CMPQ DX, DI - JE avx2_only_one_block - - // Load initial digest - MOVL (SI), AX - MOVL 4(SI), BX - MOVL 8(SI), CX - MOVL 12(SI), R8 - MOVL 16(SI), DX - MOVL 20(SI), R9 - MOVL 24(SI), R10 - MOVL 28(SI), R11 - -avx2_loop0: - // at each iteration works with one block (512 bit) - VMOVDQU (DI), Y0 - VMOVDQU 32(DI), Y1 - VMOVDQU 64(DI), Y2 - VMOVDQU 96(DI), Y3 - VMOVDQU flip_mask<>+0(SB), Y13 - - // Apply Byte Flip Mask: LE -> BE - VPSHUFB Y13, Y0, Y0 - VPSHUFB Y13, Y1, Y1 - VPSHUFB Y13, Y2, Y2 - VPSHUFB Y13, Y3, Y3 - - // Transpose data into high/low parts - VPERM2I128 $0x20, Y2, Y0, Y4 - VPERM2I128 $0x31, Y2, Y0, Y5 - VPERM2I128 $0x20, Y3, Y1, Y6 - VPERM2I128 $0x31, Y3, Y1, Y7 - LEAQ K256<>+0(SB), BP - -avx2_last_block_enter: - ADDQ $0x40, DI - MOVQ DI, 520(SP) - XORQ SI, SI - -avx2_loop1: - // Do 4 rounds and scheduling - VPADDD (BP)(SI*1), Y4, Y9 - VMOVDQU Y9, (SP)(SI*1) - MOVL AX, DI - RORXL $0x19, DX, R13 - RORXL $0x0b, DX, R14 - ADDL (SP)(SI*1), R11 - ORL CX, DI - VPALIGNR $0x04, Y6, Y7, Y0 - MOVL R9, R15 - RORXL $0x0d, AX, R12 - XORL R14, R13 - XORL R10, R15 - VPADDD Y4, Y0, Y0 - RORXL $0x06, DX, R14 - ANDL DX, R15 - XORL R14, R13 - RORXL $0x16, AX, R14 - ADDL R11, R8 - ANDL BX, DI - VPALIGNR $0x04, Y4, Y5, Y1 - XORL R12, R14 - RORXL $0x02, AX, R12 - XORL R10, R15 - VPSRLD $0x07, Y1, Y2 - XORL R12, R14 - MOVL AX, R12 - ANDL CX, R12 - ADDL R13, R15 - VPSLLD $0x19, Y1, Y3 - ORL R12, DI - ADDL R14, R11 - ADDL R15, R8 - VPOR Y2, Y3, Y3 - VPSRLD $0x12, Y1, Y2 - ADDL R15, R11 - ADDL DI, R11 - MOVL R11, DI - RORXL $0x19, R8, R13 - RORXL $0x0b, R8, R14 - ADDL 4(SP)(SI*1), R10 - ORL BX, DI - VPSRLD $0x03, Y1, Y8 - MOVL DX, R15 - RORXL $0x0d, R11, R12 - XORL R14, R13 - XORL R9, R15 - RORXL $0x06, R8, R14 - XORL R14, R13 - RORXL $0x16, R11, R14 - ANDL R8, R15 - ADDL R10, CX - VPSLLD $0x0e, Y1, Y1 - ANDL AX, DI - XORL R12, R14 - VPXOR Y1, Y3, Y3 - RORXL $0x02, R11, R12 - XORL R9, R15 - VPXOR Y2, Y3, Y3 - XORL R12, R14 - MOVL R11, R12 - ANDL BX, R12 - ADDL R13, R15 - VPXOR Y8, Y3, Y1 - VPSHUFD $0xfa, Y7, Y2 - ORL R12, DI - ADDL R14, R10 - VPADDD Y1, Y0, Y0 - ADDL R15, CX - ADDL R15, R10 - ADDL DI, R10 - VPSRLD $0x0a, Y2, Y8 - MOVL R10, DI - RORXL $0x19, CX, R13 - ADDL 8(SP)(SI*1), R9 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x0b, CX, R14 - ORL AX, DI - MOVL R8, R15 - XORL DX, R15 - RORXL $0x0d, R10, R12 - XORL R14, R13 - VPSRLQ $0x11, Y2, Y2 - ANDL CX, R15 - RORXL $0x06, CX, R14 - VPXOR Y3, Y2, Y2 - ADDL R9, BX - ANDL R11, DI - XORL R14, R13 - RORXL $0x16, R10, R14 - VPXOR Y2, Y8, Y8 - XORL DX, R15 - VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 - XORL R12, R14 - RORXL $0x02, R10, R12 - VPADDD Y8, Y0, Y0 - XORL R12, R14 - MOVL R10, R12 - ANDL AX, R12 - ADDL R13, R15 - VPSHUFD $0x50, Y0, Y2 - ORL R12, DI - ADDL R14, R9 - ADDL R15, BX - ADDL R15, R9 - ADDL DI, R9 - MOVL R9, DI - RORXL $0x19, BX, R13 - RORXL $0x0b, BX, R14 - ADDL 12(SP)(SI*1), DX - ORL R11, DI - VPSRLD $0x0a, Y2, Y11 - MOVL CX, R15 - RORXL $0x0d, R9, R12 - XORL R14, R13 - XORL R8, R15 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x06, BX, R14 - ANDL BX, R15 - ADDL DX, AX - ANDL R10, DI - VPSRLQ $0x11, Y2, Y2 - XORL R14, R13 - XORL R8, R15 - VPXOR Y3, Y2, Y2 - RORXL $0x16, R9, R14 - ADDL R13, R15 - VPXOR Y2, Y11, Y11 - XORL R12, R14 - ADDL R15, AX - RORXL $0x02, R9, R12 - VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 - VPADDD Y0, Y11, Y4 - XORL R12, R14 - MOVL R9, R12 - ANDL R11, R12 - ORL R12, DI - ADDL R14, DX - ADDL R15, DX - ADDL DI, DX - - // Do 4 rounds and scheduling - VPADDD 32(BP)(SI*1), Y5, Y9 - VMOVDQU Y9, 32(SP)(SI*1) - MOVL DX, DI - RORXL $0x19, AX, R13 - RORXL $0x0b, AX, R14 - ADDL 32(SP)(SI*1), R8 - ORL R10, DI - VPALIGNR $0x04, Y7, Y4, Y0 - MOVL BX, R15 - RORXL $0x0d, DX, R12 - XORL R14, R13 - XORL CX, R15 - VPADDD Y5, Y0, Y0 - RORXL $0x06, AX, R14 - ANDL AX, R15 - XORL R14, R13 - RORXL $0x16, DX, R14 - ADDL R8, R11 - ANDL R9, DI - VPALIGNR $0x04, Y5, Y6, Y1 - XORL R12, R14 - RORXL $0x02, DX, R12 - XORL CX, R15 - VPSRLD $0x07, Y1, Y2 - XORL R12, R14 - MOVL DX, R12 - ANDL R10, R12 - ADDL R13, R15 - VPSLLD $0x19, Y1, Y3 - ORL R12, DI - ADDL R14, R8 - ADDL R15, R11 - VPOR Y2, Y3, Y3 - VPSRLD $0x12, Y1, Y2 - ADDL R15, R8 - ADDL DI, R8 - MOVL R8, DI - RORXL $0x19, R11, R13 - RORXL $0x0b, R11, R14 - ADDL 36(SP)(SI*1), CX - ORL R9, DI - VPSRLD $0x03, Y1, Y8 - MOVL AX, R15 - RORXL $0x0d, R8, R12 - XORL R14, R13 - XORL BX, R15 - RORXL $0x06, R11, R14 - XORL R14, R13 - RORXL $0x16, R8, R14 - ANDL R11, R15 - ADDL CX, R10 - VPSLLD $0x0e, Y1, Y1 - ANDL DX, DI - XORL R12, R14 - VPXOR Y1, Y3, Y3 - RORXL $0x02, R8, R12 - XORL BX, R15 - VPXOR Y2, Y3, Y3 - XORL R12, R14 - MOVL R8, R12 - ANDL R9, R12 - ADDL R13, R15 - VPXOR Y8, Y3, Y1 - VPSHUFD $0xfa, Y4, Y2 - ORL R12, DI - ADDL R14, CX - VPADDD Y1, Y0, Y0 - ADDL R15, R10 - ADDL R15, CX - ADDL DI, CX - VPSRLD $0x0a, Y2, Y8 - MOVL CX, DI - RORXL $0x19, R10, R13 - ADDL 40(SP)(SI*1), BX - VPSRLQ $0x13, Y2, Y3 - RORXL $0x0b, R10, R14 - ORL DX, DI - MOVL R11, R15 - XORL AX, R15 - RORXL $0x0d, CX, R12 - XORL R14, R13 - VPSRLQ $0x11, Y2, Y2 - ANDL R10, R15 - RORXL $0x06, R10, R14 - VPXOR Y3, Y2, Y2 - ADDL BX, R9 - ANDL R8, DI - XORL R14, R13 - RORXL $0x16, CX, R14 - VPXOR Y2, Y8, Y8 - XORL AX, R15 - VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 - XORL R12, R14 - RORXL $0x02, CX, R12 - VPADDD Y8, Y0, Y0 - XORL R12, R14 - MOVL CX, R12 - ANDL DX, R12 - ADDL R13, R15 - VPSHUFD $0x50, Y0, Y2 - ORL R12, DI - ADDL R14, BX - ADDL R15, R9 - ADDL R15, BX - ADDL DI, BX - MOVL BX, DI - RORXL $0x19, R9, R13 - RORXL $0x0b, R9, R14 - ADDL 44(SP)(SI*1), AX - ORL R8, DI - VPSRLD $0x0a, Y2, Y11 - MOVL R10, R15 - RORXL $0x0d, BX, R12 - XORL R14, R13 - XORL R11, R15 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x06, R9, R14 - ANDL R9, R15 - ADDL AX, DX - ANDL CX, DI - VPSRLQ $0x11, Y2, Y2 - XORL R14, R13 - XORL R11, R15 - VPXOR Y3, Y2, Y2 - RORXL $0x16, BX, R14 - ADDL R13, R15 - VPXOR Y2, Y11, Y11 - XORL R12, R14 - ADDL R15, DX - RORXL $0x02, BX, R12 - VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 - VPADDD Y0, Y11, Y5 - XORL R12, R14 - MOVL BX, R12 - ANDL R8, R12 - ORL R12, DI - ADDL R14, AX - ADDL R15, AX - ADDL DI, AX - - // Do 4 rounds and scheduling - VPADDD 64(BP)(SI*1), Y6, Y9 - VMOVDQU Y9, 64(SP)(SI*1) - MOVL AX, DI - RORXL $0x19, DX, R13 - RORXL $0x0b, DX, R14 - ADDL 64(SP)(SI*1), R11 - ORL CX, DI - VPALIGNR $0x04, Y4, Y5, Y0 - MOVL R9, R15 - RORXL $0x0d, AX, R12 - XORL R14, R13 - XORL R10, R15 - VPADDD Y6, Y0, Y0 - RORXL $0x06, DX, R14 - ANDL DX, R15 - XORL R14, R13 - RORXL $0x16, AX, R14 - ADDL R11, R8 - ANDL BX, DI - VPALIGNR $0x04, Y6, Y7, Y1 - XORL R12, R14 - RORXL $0x02, AX, R12 - XORL R10, R15 - VPSRLD $0x07, Y1, Y2 - XORL R12, R14 - MOVL AX, R12 - ANDL CX, R12 - ADDL R13, R15 - VPSLLD $0x19, Y1, Y3 - ORL R12, DI - ADDL R14, R11 - ADDL R15, R8 - VPOR Y2, Y3, Y3 - VPSRLD $0x12, Y1, Y2 - ADDL R15, R11 - ADDL DI, R11 - MOVL R11, DI - RORXL $0x19, R8, R13 - RORXL $0x0b, R8, R14 - ADDL 68(SP)(SI*1), R10 - ORL BX, DI - VPSRLD $0x03, Y1, Y8 - MOVL DX, R15 - RORXL $0x0d, R11, R12 - XORL R14, R13 - XORL R9, R15 - RORXL $0x06, R8, R14 - XORL R14, R13 - RORXL $0x16, R11, R14 - ANDL R8, R15 - ADDL R10, CX - VPSLLD $0x0e, Y1, Y1 - ANDL AX, DI - XORL R12, R14 - VPXOR Y1, Y3, Y3 - RORXL $0x02, R11, R12 - XORL R9, R15 - VPXOR Y2, Y3, Y3 - XORL R12, R14 - MOVL R11, R12 - ANDL BX, R12 - ADDL R13, R15 - VPXOR Y8, Y3, Y1 - VPSHUFD $0xfa, Y5, Y2 - ORL R12, DI - ADDL R14, R10 - VPADDD Y1, Y0, Y0 - ADDL R15, CX - ADDL R15, R10 - ADDL DI, R10 - VPSRLD $0x0a, Y2, Y8 - MOVL R10, DI - RORXL $0x19, CX, R13 - ADDL 72(SP)(SI*1), R9 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x0b, CX, R14 - ORL AX, DI - MOVL R8, R15 - XORL DX, R15 - RORXL $0x0d, R10, R12 - XORL R14, R13 - VPSRLQ $0x11, Y2, Y2 - ANDL CX, R15 - RORXL $0x06, CX, R14 - VPXOR Y3, Y2, Y2 - ADDL R9, BX - ANDL R11, DI - XORL R14, R13 - RORXL $0x16, R10, R14 - VPXOR Y2, Y8, Y8 - XORL DX, R15 - VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 - XORL R12, R14 - RORXL $0x02, R10, R12 - VPADDD Y8, Y0, Y0 - XORL R12, R14 - MOVL R10, R12 - ANDL AX, R12 - ADDL R13, R15 - VPSHUFD $0x50, Y0, Y2 - ORL R12, DI - ADDL R14, R9 - ADDL R15, BX - ADDL R15, R9 - ADDL DI, R9 - MOVL R9, DI - RORXL $0x19, BX, R13 - RORXL $0x0b, BX, R14 - ADDL 76(SP)(SI*1), DX - ORL R11, DI - VPSRLD $0x0a, Y2, Y11 - MOVL CX, R15 - RORXL $0x0d, R9, R12 - XORL R14, R13 - XORL R8, R15 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x06, BX, R14 - ANDL BX, R15 - ADDL DX, AX - ANDL R10, DI - VPSRLQ $0x11, Y2, Y2 - XORL R14, R13 - XORL R8, R15 - VPXOR Y3, Y2, Y2 - RORXL $0x16, R9, R14 - ADDL R13, R15 - VPXOR Y2, Y11, Y11 - XORL R12, R14 - ADDL R15, AX - RORXL $0x02, R9, R12 - VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 - VPADDD Y0, Y11, Y6 - XORL R12, R14 - MOVL R9, R12 - ANDL R11, R12 - ORL R12, DI - ADDL R14, DX - ADDL R15, DX - ADDL DI, DX - - // Do 4 rounds and scheduling - VPADDD 96(BP)(SI*1), Y7, Y9 - VMOVDQU Y9, 96(SP)(SI*1) - MOVL DX, DI - RORXL $0x19, AX, R13 - RORXL $0x0b, AX, R14 - ADDL 96(SP)(SI*1), R8 - ORL R10, DI - VPALIGNR $0x04, Y5, Y6, Y0 - MOVL BX, R15 - RORXL $0x0d, DX, R12 - XORL R14, R13 - XORL CX, R15 - VPADDD Y7, Y0, Y0 - RORXL $0x06, AX, R14 - ANDL AX, R15 - XORL R14, R13 - RORXL $0x16, DX, R14 - ADDL R8, R11 - ANDL R9, DI - VPALIGNR $0x04, Y7, Y4, Y1 - XORL R12, R14 - RORXL $0x02, DX, R12 - XORL CX, R15 - VPSRLD $0x07, Y1, Y2 - XORL R12, R14 - MOVL DX, R12 - ANDL R10, R12 - ADDL R13, R15 - VPSLLD $0x19, Y1, Y3 - ORL R12, DI - ADDL R14, R8 - ADDL R15, R11 - VPOR Y2, Y3, Y3 - VPSRLD $0x12, Y1, Y2 - ADDL R15, R8 - ADDL DI, R8 - MOVL R8, DI - RORXL $0x19, R11, R13 - RORXL $0x0b, R11, R14 - ADDL 100(SP)(SI*1), CX - ORL R9, DI - VPSRLD $0x03, Y1, Y8 - MOVL AX, R15 - RORXL $0x0d, R8, R12 - XORL R14, R13 - XORL BX, R15 - RORXL $0x06, R11, R14 - XORL R14, R13 - RORXL $0x16, R8, R14 - ANDL R11, R15 - ADDL CX, R10 - VPSLLD $0x0e, Y1, Y1 - ANDL DX, DI - XORL R12, R14 - VPXOR Y1, Y3, Y3 - RORXL $0x02, R8, R12 - XORL BX, R15 - VPXOR Y2, Y3, Y3 - XORL R12, R14 - MOVL R8, R12 - ANDL R9, R12 - ADDL R13, R15 - VPXOR Y8, Y3, Y1 - VPSHUFD $0xfa, Y6, Y2 - ORL R12, DI - ADDL R14, CX - VPADDD Y1, Y0, Y0 - ADDL R15, R10 - ADDL R15, CX - ADDL DI, CX - VPSRLD $0x0a, Y2, Y8 - MOVL CX, DI - RORXL $0x19, R10, R13 - ADDL 104(SP)(SI*1), BX - VPSRLQ $0x13, Y2, Y3 - RORXL $0x0b, R10, R14 - ORL DX, DI - MOVL R11, R15 - XORL AX, R15 - RORXL $0x0d, CX, R12 - XORL R14, R13 - VPSRLQ $0x11, Y2, Y2 - ANDL R10, R15 - RORXL $0x06, R10, R14 - VPXOR Y3, Y2, Y2 - ADDL BX, R9 - ANDL R8, DI - XORL R14, R13 - RORXL $0x16, CX, R14 - VPXOR Y2, Y8, Y8 - XORL AX, R15 - VPSHUFB shuff_00BA<>+0(SB), Y8, Y8 - XORL R12, R14 - RORXL $0x02, CX, R12 - VPADDD Y8, Y0, Y0 - XORL R12, R14 - MOVL CX, R12 - ANDL DX, R12 - ADDL R13, R15 - VPSHUFD $0x50, Y0, Y2 - ORL R12, DI - ADDL R14, BX - ADDL R15, R9 - ADDL R15, BX - ADDL DI, BX - MOVL BX, DI - RORXL $0x19, R9, R13 - RORXL $0x0b, R9, R14 - ADDL 108(SP)(SI*1), AX - ORL R8, DI - VPSRLD $0x0a, Y2, Y11 - MOVL R10, R15 - RORXL $0x0d, BX, R12 - XORL R14, R13 - XORL R11, R15 - VPSRLQ $0x13, Y2, Y3 - RORXL $0x06, R9, R14 - ANDL R9, R15 - ADDL AX, DX - ANDL CX, DI - VPSRLQ $0x11, Y2, Y2 - XORL R14, R13 - XORL R11, R15 - VPXOR Y3, Y2, Y2 - RORXL $0x16, BX, R14 - ADDL R13, R15 - VPXOR Y2, Y11, Y11 - XORL R12, R14 - ADDL R15, DX - RORXL $0x02, BX, R12 - VPSHUFB shuff_DC00<>+0(SB), Y11, Y11 - VPADDD Y0, Y11, Y7 - XORL R12, R14 - MOVL BX, R12 - ANDL R8, R12 - ORL R12, DI - ADDL R14, AX - ADDL R15, AX - ADDL DI, AX - ADDQ $0x80, SI - CMPQ SI, $0x00000180 - JB avx2_loop1 - -avx2_loop2: - VPADDD (BP)(SI*1), Y4, Y9 - VMOVDQU Y9, (SP)(SI*1) - MOVL R9, R15 - RORXL $0x19, DX, R13 - RORXL $0x0b, DX, R14 - XORL R10, R15 - XORL R14, R13 - RORXL $0x06, DX, R14 - ANDL DX, R15 - XORL R14, R13 - RORXL $0x0d, AX, R12 - XORL R10, R15 - RORXL $0x16, AX, R14 - MOVL AX, DI - XORL R12, R14 - RORXL $0x02, AX, R12 - ADDL (SP)(SI*1), R11 - ORL CX, DI - XORL R12, R14 - MOVL AX, R12 - ANDL BX, DI - ANDL CX, R12 - ADDL R13, R15 - ADDL R11, R8 - ORL R12, DI - ADDL R14, R11 - ADDL R15, R8 - ADDL R15, R11 - MOVL DX, R15 - RORXL $0x19, R8, R13 - RORXL $0x0b, R8, R14 - XORL R9, R15 - XORL R14, R13 - RORXL $0x06, R8, R14 - ANDL R8, R15 - ADDL DI, R11 - XORL R14, R13 - RORXL $0x0d, R11, R12 - XORL R9, R15 - RORXL $0x16, R11, R14 - MOVL R11, DI - XORL R12, R14 - RORXL $0x02, R11, R12 - ADDL 4(SP)(SI*1), R10 - ORL BX, DI - XORL R12, R14 - MOVL R11, R12 - ANDL AX, DI - ANDL BX, R12 - ADDL R13, R15 - ADDL R10, CX - ORL R12, DI - ADDL R14, R10 - ADDL R15, CX - ADDL R15, R10 - MOVL R8, R15 - RORXL $0x19, CX, R13 - RORXL $0x0b, CX, R14 - XORL DX, R15 - XORL R14, R13 - RORXL $0x06, CX, R14 - ANDL CX, R15 - ADDL DI, R10 - XORL R14, R13 - RORXL $0x0d, R10, R12 - XORL DX, R15 - RORXL $0x16, R10, R14 - MOVL R10, DI - XORL R12, R14 - RORXL $0x02, R10, R12 - ADDL 8(SP)(SI*1), R9 - ORL AX, DI - XORL R12, R14 - MOVL R10, R12 - ANDL R11, DI - ANDL AX, R12 - ADDL R13, R15 - ADDL R9, BX - ORL R12, DI - ADDL R14, R9 - ADDL R15, BX - ADDL R15, R9 - MOVL CX, R15 - RORXL $0x19, BX, R13 - RORXL $0x0b, BX, R14 - XORL R8, R15 - XORL R14, R13 - RORXL $0x06, BX, R14 - ANDL BX, R15 - ADDL DI, R9 - XORL R14, R13 - RORXL $0x0d, R9, R12 - XORL R8, R15 - RORXL $0x16, R9, R14 - MOVL R9, DI - XORL R12, R14 - RORXL $0x02, R9, R12 - ADDL 12(SP)(SI*1), DX - ORL R11, DI - XORL R12, R14 - MOVL R9, R12 - ANDL R10, DI - ANDL R11, R12 - ADDL R13, R15 - ADDL DX, AX - ORL R12, DI - ADDL R14, DX - ADDL R15, AX - ADDL R15, DX - ADDL DI, DX - VPADDD 32(BP)(SI*1), Y5, Y9 - VMOVDQU Y9, 32(SP)(SI*1) - MOVL BX, R15 - RORXL $0x19, AX, R13 - RORXL $0x0b, AX, R14 - XORL CX, R15 - XORL R14, R13 - RORXL $0x06, AX, R14 - ANDL AX, R15 - XORL R14, R13 - RORXL $0x0d, DX, R12 - XORL CX, R15 - RORXL $0x16, DX, R14 - MOVL DX, DI - XORL R12, R14 - RORXL $0x02, DX, R12 - ADDL 32(SP)(SI*1), R8 - ORL R10, DI - XORL R12, R14 - MOVL DX, R12 - ANDL R9, DI - ANDL R10, R12 - ADDL R13, R15 - ADDL R8, R11 - ORL R12, DI - ADDL R14, R8 - ADDL R15, R11 - ADDL R15, R8 - MOVL AX, R15 - RORXL $0x19, R11, R13 - RORXL $0x0b, R11, R14 - XORL BX, R15 - XORL R14, R13 - RORXL $0x06, R11, R14 - ANDL R11, R15 - ADDL DI, R8 - XORL R14, R13 - RORXL $0x0d, R8, R12 - XORL BX, R15 - RORXL $0x16, R8, R14 - MOVL R8, DI - XORL R12, R14 - RORXL $0x02, R8, R12 - ADDL 36(SP)(SI*1), CX - ORL R9, DI - XORL R12, R14 - MOVL R8, R12 - ANDL DX, DI - ANDL R9, R12 - ADDL R13, R15 - ADDL CX, R10 - ORL R12, DI - ADDL R14, CX - ADDL R15, R10 - ADDL R15, CX - MOVL R11, R15 - RORXL $0x19, R10, R13 - RORXL $0x0b, R10, R14 - XORL AX, R15 - XORL R14, R13 - RORXL $0x06, R10, R14 - ANDL R10, R15 - ADDL DI, CX - XORL R14, R13 - RORXL $0x0d, CX, R12 - XORL AX, R15 - RORXL $0x16, CX, R14 - MOVL CX, DI - XORL R12, R14 - RORXL $0x02, CX, R12 - ADDL 40(SP)(SI*1), BX - ORL DX, DI - XORL R12, R14 - MOVL CX, R12 - ANDL R8, DI - ANDL DX, R12 - ADDL R13, R15 - ADDL BX, R9 - ORL R12, DI - ADDL R14, BX - ADDL R15, R9 - ADDL R15, BX - MOVL R10, R15 - RORXL $0x19, R9, R13 - RORXL $0x0b, R9, R14 - XORL R11, R15 - XORL R14, R13 - RORXL $0x06, R9, R14 - ANDL R9, R15 - ADDL DI, BX - XORL R14, R13 - RORXL $0x0d, BX, R12 - XORL R11, R15 - RORXL $0x16, BX, R14 - MOVL BX, DI - XORL R12, R14 - RORXL $0x02, BX, R12 - ADDL 44(SP)(SI*1), AX - ORL R8, DI - XORL R12, R14 - MOVL BX, R12 - ANDL CX, DI - ANDL R8, R12 - ADDL R13, R15 - ADDL AX, DX - ORL R12, DI - ADDL R14, AX - ADDL R15, DX - ADDL R15, AX - ADDL DI, AX - ADDQ $0x40, SI - VMOVDQU Y6, Y4 - VMOVDQU Y7, Y5 - CMPQ SI, $0x00000200 - JB avx2_loop2 - MOVQ dig+0(FP), SI - MOVQ 520(SP), DI - ADDL AX, (SI) - MOVL (SI), AX - ADDL BX, 4(SI) - MOVL 4(SI), BX - ADDL CX, 8(SI) - MOVL 8(SI), CX - ADDL R8, 12(SI) - MOVL 12(SI), R8 - ADDL DX, 16(SI) - MOVL 16(SI), DX - ADDL R9, 20(SI) - MOVL 20(SI), R9 - ADDL R10, 24(SI) - MOVL 24(SI), R10 - ADDL R11, 28(SI) - MOVL 28(SI), R11 - CMPQ 512(SP), DI - JB done_hash - XORQ SI, SI - -avx2_loop3: - MOVL R9, R15 - RORXL $0x19, DX, R13 - RORXL $0x0b, DX, R14 - XORL R10, R15 - XORL R14, R13 - RORXL $0x06, DX, R14 - ANDL DX, R15 - XORL R14, R13 - RORXL $0x0d, AX, R12 - XORL R10, R15 - RORXL $0x16, AX, R14 - MOVL AX, DI - XORL R12, R14 - RORXL $0x02, AX, R12 - ADDL 16(SP)(SI*1), R11 - ORL CX, DI - XORL R12, R14 - MOVL AX, R12 - ANDL BX, DI - ANDL CX, R12 - ADDL R13, R15 - ADDL R11, R8 - ORL R12, DI - ADDL R14, R11 - ADDL R15, R8 - ADDL R15, R11 - MOVL DX, R15 - RORXL $0x19, R8, R13 - RORXL $0x0b, R8, R14 - XORL R9, R15 - XORL R14, R13 - RORXL $0x06, R8, R14 - ANDL R8, R15 - ADDL DI, R11 - XORL R14, R13 - RORXL $0x0d, R11, R12 - XORL R9, R15 - RORXL $0x16, R11, R14 - MOVL R11, DI - XORL R12, R14 - RORXL $0x02, R11, R12 - ADDL 20(SP)(SI*1), R10 - ORL BX, DI - XORL R12, R14 - MOVL R11, R12 - ANDL AX, DI - ANDL BX, R12 - ADDL R13, R15 - ADDL R10, CX - ORL R12, DI - ADDL R14, R10 - ADDL R15, CX - ADDL R15, R10 - MOVL R8, R15 - RORXL $0x19, CX, R13 - RORXL $0x0b, CX, R14 - XORL DX, R15 - XORL R14, R13 - RORXL $0x06, CX, R14 - ANDL CX, R15 - ADDL DI, R10 - XORL R14, R13 - RORXL $0x0d, R10, R12 - XORL DX, R15 - RORXL $0x16, R10, R14 - MOVL R10, DI - XORL R12, R14 - RORXL $0x02, R10, R12 - ADDL 24(SP)(SI*1), R9 - ORL AX, DI - XORL R12, R14 - MOVL R10, R12 - ANDL R11, DI - ANDL AX, R12 - ADDL R13, R15 - ADDL R9, BX - ORL R12, DI - ADDL R14, R9 - ADDL R15, BX - ADDL R15, R9 - MOVL CX, R15 - RORXL $0x19, BX, R13 - RORXL $0x0b, BX, R14 - XORL R8, R15 - XORL R14, R13 - RORXL $0x06, BX, R14 - ANDL BX, R15 - ADDL DI, R9 - XORL R14, R13 - RORXL $0x0d, R9, R12 - XORL R8, R15 - RORXL $0x16, R9, R14 - MOVL R9, DI - XORL R12, R14 - RORXL $0x02, R9, R12 - ADDL 28(SP)(SI*1), DX - ORL R11, DI - XORL R12, R14 - MOVL R9, R12 - ANDL R10, DI - ANDL R11, R12 - ADDL R13, R15 - ADDL DX, AX - ORL R12, DI - ADDL R14, DX - ADDL R15, AX - ADDL R15, DX - ADDL DI, DX - MOVL BX, R15 - RORXL $0x19, AX, R13 - RORXL $0x0b, AX, R14 - XORL CX, R15 - XORL R14, R13 - RORXL $0x06, AX, R14 - ANDL AX, R15 - XORL R14, R13 - RORXL $0x0d, DX, R12 - XORL CX, R15 - RORXL $0x16, DX, R14 - MOVL DX, DI - XORL R12, R14 - RORXL $0x02, DX, R12 - ADDL 48(SP)(SI*1), R8 - ORL R10, DI - XORL R12, R14 - MOVL DX, R12 - ANDL R9, DI - ANDL R10, R12 - ADDL R13, R15 - ADDL R8, R11 - ORL R12, DI - ADDL R14, R8 - ADDL R15, R11 - ADDL R15, R8 - MOVL AX, R15 - RORXL $0x19, R11, R13 - RORXL $0x0b, R11, R14 - XORL BX, R15 - XORL R14, R13 - RORXL $0x06, R11, R14 - ANDL R11, R15 - ADDL DI, R8 - XORL R14, R13 - RORXL $0x0d, R8, R12 - XORL BX, R15 - RORXL $0x16, R8, R14 - MOVL R8, DI - XORL R12, R14 - RORXL $0x02, R8, R12 - ADDL 52(SP)(SI*1), CX - ORL R9, DI - XORL R12, R14 - MOVL R8, R12 - ANDL DX, DI - ANDL R9, R12 - ADDL R13, R15 - ADDL CX, R10 - ORL R12, DI - ADDL R14, CX - ADDL R15, R10 - ADDL R15, CX - MOVL R11, R15 - RORXL $0x19, R10, R13 - RORXL $0x0b, R10, R14 - XORL AX, R15 - XORL R14, R13 - RORXL $0x06, R10, R14 - ANDL R10, R15 - ADDL DI, CX - XORL R14, R13 - RORXL $0x0d, CX, R12 - XORL AX, R15 - RORXL $0x16, CX, R14 - MOVL CX, DI - XORL R12, R14 - RORXL $0x02, CX, R12 - ADDL 56(SP)(SI*1), BX - ORL DX, DI - XORL R12, R14 - MOVL CX, R12 - ANDL R8, DI - ANDL DX, R12 - ADDL R13, R15 - ADDL BX, R9 - ORL R12, DI - ADDL R14, BX - ADDL R15, R9 - ADDL R15, BX - MOVL R10, R15 - RORXL $0x19, R9, R13 - RORXL $0x0b, R9, R14 - XORL R11, R15 - XORL R14, R13 - RORXL $0x06, R9, R14 - ANDL R9, R15 - ADDL DI, BX - XORL R14, R13 - RORXL $0x0d, BX, R12 - XORL R11, R15 - RORXL $0x16, BX, R14 - MOVL BX, DI - XORL R12, R14 - RORXL $0x02, BX, R12 - ADDL 60(SP)(SI*1), AX - ORL R8, DI - XORL R12, R14 - MOVL BX, R12 - ANDL CX, DI - ANDL R8, R12 - ADDL R13, R15 - ADDL AX, DX - ORL R12, DI - ADDL R14, AX - ADDL R15, DX - ADDL R15, AX - ADDL DI, AX - ADDQ $0x40, SI - CMPQ SI, $0x00000200 - JB avx2_loop3 - MOVQ dig+0(FP), SI - MOVQ 520(SP), DI - ADDQ $0x40, DI - ADDL AX, (SI) - MOVL (SI), AX - ADDL BX, 4(SI) - MOVL 4(SI), BX - ADDL CX, 8(SI) - MOVL 8(SI), CX - ADDL R8, 12(SI) - MOVL 12(SI), R8 - ADDL DX, 16(SI) - MOVL 16(SI), DX - ADDL R9, 20(SI) - MOVL 20(SI), R9 - ADDL R10, 24(SI) - MOVL 24(SI), R10 - ADDL R11, 28(SI) - MOVL 28(SI), R11 - CMPQ 512(SP), DI - JA avx2_loop0 - JB done_hash - -avx2_do_last_block: - VMOVDQU (DI), X4 - VMOVDQU 16(DI), X5 - VMOVDQU 32(DI), X6 - VMOVDQU 48(DI), X7 - VMOVDQU flip_mask<>+0(SB), Y13 - VPSHUFB X13, X4, X4 - VPSHUFB X13, X5, X5 - VPSHUFB X13, X6, X6 - VPSHUFB X13, X7, X7 - LEAQ K256<>+0(SB), BP - JMP avx2_last_block_enter - -avx2_only_one_block: - MOVL (SI), AX - MOVL 4(SI), BX - MOVL 8(SI), CX - MOVL 12(SI), R8 - MOVL 16(SI), DX - MOVL 20(SI), R9 - MOVL 24(SI), R10 - MOVL 28(SI), R11 - JMP avx2_do_last_block - -done_hash: - VZEROUPPER - RET - -sha_ni: - MOVQ dig+0(FP), DI - MOVQ p_base+8(FP), SI - MOVQ p_len+16(FP), DX - SHRQ $0x06, DX - SHLQ $0x06, DX - CMPQ DX, $0x00 - JEQ done - ADDQ SI, DX - VMOVDQU (DI), X1 - VMOVDQU 16(DI), X2 - PSHUFD $0xb1, X1, X1 - PSHUFD $0x1b, X2, X2 - VMOVDQA X1, X7 - PALIGNR $0x08, X2, X1 - PBLENDW $0xf0, X7, X2 - VMOVDQA flip_mask<>+0(SB), X8 - LEAQ K256<>+0(SB), AX - -roundLoop: - // save hash values for addition after rounds - VMOVDQA X1, X9 - VMOVDQA X2, X10 - - // do rounds 0-59 - VMOVDQU (SI), X0 - PSHUFB X8, X0 - VMOVDQA X0, X3 - PADDD (AX), X0 - SHA256RNDS2 X0, X1, X2 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - VMOVDQU 16(SI), X0 - PSHUFB X8, X0 - VMOVDQA X0, X4 - PADDD 32(AX), X0 - SHA256RNDS2 X0, X1, X2 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X4, X3 - VMOVDQU 32(SI), X0 - PSHUFB X8, X0 - VMOVDQA X0, X5 - PADDD 64(AX), X0 - SHA256RNDS2 X0, X1, X2 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X5, X4 - VMOVDQU 48(SI), X0 - PSHUFB X8, X0 - VMOVDQA X0, X6 - PADDD 96(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X6, X7 - PALIGNR $0x04, X5, X7 - PADDD X7, X3 - SHA256MSG2 X6, X3 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X6, X5 - VMOVDQA X3, X0 - PADDD 128(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X3, X7 - PALIGNR $0x04, X6, X7 - PADDD X7, X4 - SHA256MSG2 X3, X4 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X3, X6 - VMOVDQA X4, X0 - PADDD 160(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X4, X7 - PALIGNR $0x04, X3, X7 - PADDD X7, X5 - SHA256MSG2 X4, X5 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X4, X3 - VMOVDQA X5, X0 - PADDD 192(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X5, X7 - PALIGNR $0x04, X4, X7 - PADDD X7, X6 - SHA256MSG2 X5, X6 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X5, X4 - VMOVDQA X6, X0 - PADDD 224(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X6, X7 - PALIGNR $0x04, X5, X7 - PADDD X7, X3 - SHA256MSG2 X6, X3 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X6, X5 - VMOVDQA X3, X0 - PADDD 256(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X3, X7 - PALIGNR $0x04, X6, X7 - PADDD X7, X4 - SHA256MSG2 X3, X4 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X3, X6 - VMOVDQA X4, X0 - PADDD 288(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X4, X7 - PALIGNR $0x04, X3, X7 - PADDD X7, X5 - SHA256MSG2 X4, X5 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X4, X3 - VMOVDQA X5, X0 - PADDD 320(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X5, X7 - PALIGNR $0x04, X4, X7 - PADDD X7, X6 - SHA256MSG2 X5, X6 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X5, X4 - VMOVDQA X6, X0 - PADDD 352(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X6, X7 - PALIGNR $0x04, X5, X7 - PADDD X7, X3 - SHA256MSG2 X6, X3 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X6, X5 - VMOVDQA X3, X0 - PADDD 384(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X3, X7 - PALIGNR $0x04, X6, X7 - PADDD X7, X4 - SHA256MSG2 X3, X4 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - SHA256MSG1 X3, X6 - VMOVDQA X4, X0 - PADDD 416(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X4, X7 - PALIGNR $0x04, X3, X7 - PADDD X7, X5 - SHA256MSG2 X4, X5 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - VMOVDQA X5, X0 - PADDD 448(AX), X0 - SHA256RNDS2 X0, X1, X2 - VMOVDQA X5, X7 - PALIGNR $0x04, X4, X7 - PADDD X7, X6 - SHA256MSG2 X5, X6 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - - // do rounds 60-63 - VMOVDQA X6, X0 - PADDD 480(AX), X0 - SHA256RNDS2 X0, X1, X2 - PSHUFD $0x0e, X0, X0 - SHA256RNDS2 X0, X2, X1 - - // add current hash values with previously saved - PADDD X9, X1 - PADDD X10, X2 - - // advance data pointer; loop until buffer empty - ADDQ $0x40, SI - CMPQ DX, SI - JNE roundLoop - - // write hash values back in the correct order - PSHUFD $0x1b, X1, X1 - PSHUFD $0xb1, X2, X2 - VMOVDQA X1, X7 - PBLENDW $0xf0, X2, X1 - PALIGNR $0x08, X7, X2 - VMOVDQU X1, (DI) - VMOVDQU X2, 16(DI) - -done: - RET - -DATA flip_mask<>+0(SB)/8, $0x0405060700010203 -DATA flip_mask<>+8(SB)/8, $0x0c0d0e0f08090a0b -DATA flip_mask<>+16(SB)/8, $0x0405060700010203 -DATA flip_mask<>+24(SB)/8, $0x0c0d0e0f08090a0b -GLOBL flip_mask<>(SB), RODATA, $32 - -DATA K256<>+0(SB)/4, $0x428a2f98 -DATA K256<>+4(SB)/4, $0x71374491 -DATA K256<>+8(SB)/4, $0xb5c0fbcf -DATA K256<>+12(SB)/4, $0xe9b5dba5 -DATA K256<>+16(SB)/4, $0x428a2f98 -DATA K256<>+20(SB)/4, $0x71374491 -DATA K256<>+24(SB)/4, $0xb5c0fbcf -DATA K256<>+28(SB)/4, $0xe9b5dba5 -DATA K256<>+32(SB)/4, $0x3956c25b -DATA K256<>+36(SB)/4, $0x59f111f1 -DATA K256<>+40(SB)/4, $0x923f82a4 -DATA K256<>+44(SB)/4, $0xab1c5ed5 -DATA K256<>+48(SB)/4, $0x3956c25b -DATA K256<>+52(SB)/4, $0x59f111f1 -DATA K256<>+56(SB)/4, $0x923f82a4 -DATA K256<>+60(SB)/4, $0xab1c5ed5 -DATA K256<>+64(SB)/4, $0xd807aa98 -DATA K256<>+68(SB)/4, $0x12835b01 -DATA K256<>+72(SB)/4, $0x243185be -DATA K256<>+76(SB)/4, $0x550c7dc3 -DATA K256<>+80(SB)/4, $0xd807aa98 -DATA K256<>+84(SB)/4, $0x12835b01 -DATA K256<>+88(SB)/4, $0x243185be -DATA K256<>+92(SB)/4, $0x550c7dc3 -DATA K256<>+96(SB)/4, $0x72be5d74 -DATA K256<>+100(SB)/4, $0x80deb1fe -DATA K256<>+104(SB)/4, $0x9bdc06a7 -DATA K256<>+108(SB)/4, $0xc19bf174 -DATA K256<>+112(SB)/4, $0x72be5d74 -DATA K256<>+116(SB)/4, $0x80deb1fe -DATA K256<>+120(SB)/4, $0x9bdc06a7 -DATA K256<>+124(SB)/4, $0xc19bf174 -DATA K256<>+128(SB)/4, $0xe49b69c1 -DATA K256<>+132(SB)/4, $0xefbe4786 -DATA K256<>+136(SB)/4, $0x0fc19dc6 -DATA K256<>+140(SB)/4, $0x240ca1cc -DATA K256<>+144(SB)/4, $0xe49b69c1 -DATA K256<>+148(SB)/4, $0xefbe4786 -DATA K256<>+152(SB)/4, $0x0fc19dc6 -DATA K256<>+156(SB)/4, $0x240ca1cc -DATA K256<>+160(SB)/4, $0x2de92c6f -DATA K256<>+164(SB)/4, $0x4a7484aa -DATA K256<>+168(SB)/4, $0x5cb0a9dc -DATA K256<>+172(SB)/4, $0x76f988da -DATA K256<>+176(SB)/4, $0x2de92c6f -DATA K256<>+180(SB)/4, $0x4a7484aa -DATA K256<>+184(SB)/4, $0x5cb0a9dc -DATA K256<>+188(SB)/4, $0x76f988da -DATA K256<>+192(SB)/4, $0x983e5152 -DATA K256<>+196(SB)/4, $0xa831c66d -DATA K256<>+200(SB)/4, $0xb00327c8 -DATA K256<>+204(SB)/4, $0xbf597fc7 -DATA K256<>+208(SB)/4, $0x983e5152 -DATA K256<>+212(SB)/4, $0xa831c66d -DATA K256<>+216(SB)/4, $0xb00327c8 -DATA K256<>+220(SB)/4, $0xbf597fc7 -DATA K256<>+224(SB)/4, $0xc6e00bf3 -DATA K256<>+228(SB)/4, $0xd5a79147 -DATA K256<>+232(SB)/4, $0x06ca6351 -DATA K256<>+236(SB)/4, $0x14292967 -DATA K256<>+240(SB)/4, $0xc6e00bf3 -DATA K256<>+244(SB)/4, $0xd5a79147 -DATA K256<>+248(SB)/4, $0x06ca6351 -DATA K256<>+252(SB)/4, $0x14292967 -DATA K256<>+256(SB)/4, $0x27b70a85 -DATA K256<>+260(SB)/4, $0x2e1b2138 -DATA K256<>+264(SB)/4, $0x4d2c6dfc -DATA K256<>+268(SB)/4, $0x53380d13 -DATA K256<>+272(SB)/4, $0x27b70a85 -DATA K256<>+276(SB)/4, $0x2e1b2138 -DATA K256<>+280(SB)/4, $0x4d2c6dfc -DATA K256<>+284(SB)/4, $0x53380d13 -DATA K256<>+288(SB)/4, $0x650a7354 -DATA K256<>+292(SB)/4, $0x766a0abb -DATA K256<>+296(SB)/4, $0x81c2c92e -DATA K256<>+300(SB)/4, $0x92722c85 -DATA K256<>+304(SB)/4, $0x650a7354 -DATA K256<>+308(SB)/4, $0x766a0abb -DATA K256<>+312(SB)/4, $0x81c2c92e -DATA K256<>+316(SB)/4, $0x92722c85 -DATA K256<>+320(SB)/4, $0xa2bfe8a1 -DATA K256<>+324(SB)/4, $0xa81a664b -DATA K256<>+328(SB)/4, $0xc24b8b70 -DATA K256<>+332(SB)/4, $0xc76c51a3 -DATA K256<>+336(SB)/4, $0xa2bfe8a1 -DATA K256<>+340(SB)/4, $0xa81a664b -DATA K256<>+344(SB)/4, $0xc24b8b70 -DATA K256<>+348(SB)/4, $0xc76c51a3 -DATA K256<>+352(SB)/4, $0xd192e819 -DATA K256<>+356(SB)/4, $0xd6990624 -DATA K256<>+360(SB)/4, $0xf40e3585 -DATA K256<>+364(SB)/4, $0x106aa070 -DATA K256<>+368(SB)/4, $0xd192e819 -DATA K256<>+372(SB)/4, $0xd6990624 -DATA K256<>+376(SB)/4, $0xf40e3585 -DATA K256<>+380(SB)/4, $0x106aa070 -DATA K256<>+384(SB)/4, $0x19a4c116 -DATA K256<>+388(SB)/4, $0x1e376c08 -DATA K256<>+392(SB)/4, $0x2748774c -DATA K256<>+396(SB)/4, $0x34b0bcb5 -DATA K256<>+400(SB)/4, $0x19a4c116 -DATA K256<>+404(SB)/4, $0x1e376c08 -DATA K256<>+408(SB)/4, $0x2748774c -DATA K256<>+412(SB)/4, $0x34b0bcb5 -DATA K256<>+416(SB)/4, $0x391c0cb3 -DATA K256<>+420(SB)/4, $0x4ed8aa4a -DATA K256<>+424(SB)/4, $0x5b9cca4f -DATA K256<>+428(SB)/4, $0x682e6ff3 -DATA K256<>+432(SB)/4, $0x391c0cb3 -DATA K256<>+436(SB)/4, $0x4ed8aa4a -DATA K256<>+440(SB)/4, $0x5b9cca4f -DATA K256<>+444(SB)/4, $0x682e6ff3 -DATA K256<>+448(SB)/4, $0x748f82ee -DATA K256<>+452(SB)/4, $0x78a5636f -DATA K256<>+456(SB)/4, $0x84c87814 -DATA K256<>+460(SB)/4, $0x8cc70208 -DATA K256<>+464(SB)/4, $0x748f82ee -DATA K256<>+468(SB)/4, $0x78a5636f -DATA K256<>+472(SB)/4, $0x84c87814 -DATA K256<>+476(SB)/4, $0x8cc70208 -DATA K256<>+480(SB)/4, $0x90befffa -DATA K256<>+484(SB)/4, $0xa4506ceb -DATA K256<>+488(SB)/4, $0xbef9a3f7 -DATA K256<>+492(SB)/4, $0xc67178f2 -DATA K256<>+496(SB)/4, $0x90befffa -DATA K256<>+500(SB)/4, $0xa4506ceb -DATA K256<>+504(SB)/4, $0xbef9a3f7 -DATA K256<>+508(SB)/4, $0xc67178f2 -GLOBL K256<>(SB), RODATA|NOPTR, $512 - -DATA shuff_00BA<>+0(SB)/8, $0x0b0a090803020100 -DATA shuff_00BA<>+8(SB)/8, $0xffffffffffffffff -DATA shuff_00BA<>+16(SB)/8, $0x0b0a090803020100 -DATA shuff_00BA<>+24(SB)/8, $0xffffffffffffffff -GLOBL shuff_00BA<>(SB), RODATA, $32 - -DATA shuff_DC00<>+0(SB)/8, $0xffffffffffffffff -DATA shuff_DC00<>+8(SB)/8, $0x0b0a090803020100 -DATA shuff_DC00<>+16(SB)/8, $0xffffffffffffffff -DATA shuff_DC00<>+24(SB)/8, $0x0b0a090803020100 -GLOBL shuff_DC00<>(SB), RODATA, $32 diff --git a/crypto/sha256/sha256block_arm64.go b/crypto/sha256/sha256block_arm64.go deleted file mode 100644 index 2288227cac4..00000000000 --- a/crypto/sha256/sha256block_arm64.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha256 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -var k = _K - -//go:noescape -func sha256block(h []uint32, p []byte, k []uint32) - -func block(dig *digest, p []byte) { - if !cpu.ARM64.HasSHA2 { - blockGeneric(dig, p) - } else { - h := dig.h[:] - sha256block(h, p, k) - } -} diff --git a/crypto/sha256/sha256block_s390x.go b/crypto/sha256/sha256block_s390x.go deleted file mode 100644 index 0fbc6a787d6..00000000000 --- a/crypto/sha256/sha256block_s390x.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha256 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -var useAsm = cpu.S390X.HasSHA256 diff --git a/crypto/sha3/sha3.go b/crypto/sha3/sha3.go new file mode 100644 index 00000000000..f5d9f949565 --- /dev/null +++ b/crypto/sha3/sha3.go @@ -0,0 +1,248 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha3 implements the SHA-3 hash algorithms and the SHAKE extendable +// output functions defined in FIPS 202. +package sha3 + +import ( + _ "unsafe" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha3" +) + +func init() { + crypto.RegisterHash(crypto.SHA3_224, func() hash.Hash { return New224() }) + crypto.RegisterHash(crypto.SHA3_256, func() hash.Hash { return New256() }) + crypto.RegisterHash(crypto.SHA3_384, func() hash.Hash { return New384() }) + crypto.RegisterHash(crypto.SHA3_512, func() hash.Hash { return New512() }) +} + +// Sum224 returns the SHA3-224 hash of data. +func Sum224(data []byte) [28]byte { + var out [28]byte + h := sha3.New224() + h.Write(data) + h.Sum(out[:0]) + return out +} + +// Sum256 returns the SHA3-256 hash of data. +func Sum256(data []byte) [32]byte { + var out [32]byte + h := sha3.New256() + h.Write(data) + h.Sum(out[:0]) + return out +} + +// Sum384 returns the SHA3-384 hash of data. +func Sum384(data []byte) [48]byte { + var out [48]byte + h := sha3.New384() + h.Write(data) + h.Sum(out[:0]) + return out +} + +// Sum512 returns the SHA3-512 hash of data. +func Sum512(data []byte) [64]byte { + var out [64]byte + h := sha3.New512() + h.Write(data) + h.Sum(out[:0]) + return out +} + +// SumSHAKE128 applies the SHAKE128 extendable output function to data and +// returns an output of the given length in bytes. +func SumSHAKE128(data []byte, length int) []byte { + // Outline the allocation for up to 256 bits of output to the caller's stack. + out := make([]byte, 32) + return sumSHAKE128(out, data, length) +} + +func sumSHAKE128(out, data []byte, length int) []byte { + if len(out) < length { + out = make([]byte, length) + } else { + out = out[:length] + } + h := sha3.NewShake128() + h.Write(data) + h.Read(out) + return out +} + +// SumSHAKE256 applies the SHAKE256 extendable output function to data and +// returns an output of the given length in bytes. +func SumSHAKE256(data []byte, length int) []byte { + // Outline the allocation for up to 512 bits of output to the caller's stack. + out := make([]byte, 64) + return sumSHAKE256(out, data, length) +} + +func sumSHAKE256(out, data []byte, length int) []byte { + if len(out) < length { + out = make([]byte, length) + } else { + out = out[:length] + } + h := sha3.NewShake256() + h.Write(data) + h.Read(out) + return out +} + +// SHA3 is an instance of a SHA-3 hash. It implements [hash.Hash]. +type SHA3 struct { + s sha3.Digest +} + +//go:linkname fips140hash_sha3Unwrap github.com/runZeroInc/excrypto/crypto/internal/fips140hash.sha3Unwrap +func fips140hash_sha3Unwrap(sha3 *SHA3) *sha3.Digest { + return &sha3.s +} + +// New224 creates a new SHA3-224 hash. +func New224() *SHA3 { + return &SHA3{*sha3.New224()} +} + +// New256 creates a new SHA3-256 hash. +func New256() *SHA3 { + return &SHA3{*sha3.New256()} +} + +// New384 creates a new SHA3-384 hash. +func New384() *SHA3 { + return &SHA3{*sha3.New384()} +} + +// New512 creates a new SHA3-512 hash. +func New512() *SHA3 { + return &SHA3{*sha3.New512()} +} + +// Write absorbs more data into the hash's state. +func (s *SHA3) Write(p []byte) (n int, err error) { + return s.s.Write(p) +} + +// Sum appends the current hash to b and returns the resulting slice. +func (s *SHA3) Sum(b []byte) []byte { + return s.s.Sum(b) +} + +// Reset resets the hash to its initial state. +func (s *SHA3) Reset() { + s.s.Reset() +} + +// Size returns the number of bytes Sum will produce. +func (s *SHA3) Size() int { + return s.s.Size() +} + +// BlockSize returns the hash's rate. +func (s *SHA3) BlockSize() int { + return s.s.BlockSize() +} + +// MarshalBinary implements [encoding.BinaryMarshaler]. +func (s *SHA3) MarshalBinary() ([]byte, error) { + return s.s.MarshalBinary() +} + +// AppendBinary implements [encoding.BinaryAppender]. +func (s *SHA3) AppendBinary(p []byte) ([]byte, error) { + return s.s.AppendBinary(p) +} + +// UnmarshalBinary implements [encoding.BinaryUnmarshaler]. +func (s *SHA3) UnmarshalBinary(data []byte) error { + return s.s.UnmarshalBinary(data) +} + +// Clone implements [hash.Cloner]. +func (d *SHA3) Clone() (hash.Cloner, error) { + r := *d + return &r, nil +} + +// SHAKE is an instance of a SHAKE extendable output function. +type SHAKE struct { + s sha3.SHAKE +} + +// NewSHAKE128 creates a new SHAKE128 XOF. +func NewSHAKE128() *SHAKE { + return &SHAKE{*sha3.NewShake128()} +} + +// NewSHAKE256 creates a new SHAKE256 XOF. +func NewSHAKE256() *SHAKE { + return &SHAKE{*sha3.NewShake256()} +} + +// NewCSHAKE128 creates a new cSHAKE128 XOF. +// +// N is used to define functions based on cSHAKE, it can be empty when plain +// cSHAKE is desired. S is a customization byte string used for domain +// separation. When N and S are both empty, this is equivalent to NewSHAKE128. +func NewCSHAKE128(N, S []byte) *SHAKE { + return &SHAKE{*sha3.NewCShake128(N, S)} +} + +// NewCSHAKE256 creates a new cSHAKE256 XOF. +// +// N is used to define functions based on cSHAKE, it can be empty when plain +// cSHAKE is desired. S is a customization byte string used for domain +// separation. When N and S are both empty, this is equivalent to NewSHAKE256. +func NewCSHAKE256(N, S []byte) *SHAKE { + return &SHAKE{*sha3.NewCShake256(N, S)} +} + +// Write absorbs more data into the XOF's state. +// +// It panics if any output has already been read. +func (s *SHAKE) Write(p []byte) (n int, err error) { + return s.s.Write(p) +} + +// Read squeezes more output from the XOF. +// +// Any call to Write after a call to Read will panic. +func (s *SHAKE) Read(p []byte) (n int, err error) { + return s.s.Read(p) +} + +// Reset resets the XOF to its initial state. +func (s *SHAKE) Reset() { + s.s.Reset() +} + +// BlockSize returns the rate of the XOF. +func (s *SHAKE) BlockSize() int { + return s.s.BlockSize() +} + +// MarshalBinary implements [encoding.BinaryMarshaler]. +func (s *SHAKE) MarshalBinary() ([]byte, error) { + return s.s.MarshalBinary() +} + +// AppendBinary implements [encoding.BinaryAppender]. +func (s *SHAKE) AppendBinary(p []byte) ([]byte, error) { + return s.s.AppendBinary(p) +} + +// UnmarshalBinary implements [encoding.BinaryUnmarshaler]. +func (s *SHAKE) UnmarshalBinary(data []byte) error { + return s.s.UnmarshalBinary(data) +} diff --git a/crypto/sha3/sha3_test.go b/crypto/sha3/sha3_test.go new file mode 100644 index 00000000000..83ad6a45d64 --- /dev/null +++ b/crypto/sha3/sha3_test.go @@ -0,0 +1,504 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3_test + +import ( + "bytes" + . "crypto/sha3" + "encoding/hex" + "io" + "math/rand" + "strings" + "testing" + + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" +) + +const testString = "brekeccakkeccak koax koax" + +// testDigests contains functions returning hash.Hash instances +// with output-length equal to the KAT length for SHA-3, Keccak +// and SHAKE instances. +var testDigests = map[string]func() *SHA3{ + "SHA3-224": New224, + "SHA3-256": New256, + "SHA3-384": New384, + "SHA3-512": New512, +} + +// testShakes contains functions that return *sha3.SHAKE instances for +// with output-length equal to the KAT length. +var testShakes = map[string]struct { + constructor func(N []byte, S []byte) *SHAKE + defAlgoName string + defCustomStr string +}{ + // NewCSHAKE without customization produces same result as SHAKE + "SHAKE128": {NewCSHAKE128, "", ""}, + "SHAKE256": {NewCSHAKE256, "", ""}, + "cSHAKE128": {NewCSHAKE128, "CSHAKE128", "CustomString"}, + "cSHAKE256": {NewCSHAKE256, "CSHAKE256", "CustomString"}, +} + +func TestSHA3Hash(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) { + for name, f := range testDigests { + t.Run(name, func(t *testing.T) { + cryptotest.TestHash(t, func() hash.Hash { return f() }) + }) + } + }) +} + +// TestUnalignedWrite tests that writing data in an arbitrary pattern with +// small input buffers. +func TestUnalignedWrite(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testUnalignedWrite) +} + +func testUnalignedWrite(t *testing.T) { + buf := sequentialBytes(0x10000) + for alg, df := range testDigests { + d := df() + d.Reset() + d.Write(buf) + want := d.Sum(nil) + d.Reset() + for i := 0; i < len(buf); { + // Cycle through offsets which make a 137 byte sequence. + // Because 137 is prime this sequence should exercise all corner cases. + offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} + for _, j := range offsets { + if v := len(buf) - i; v < j { + j = v + } + d.Write(buf[i : i+j]) + i += j + } + } + got := d.Sum(nil) + if !bytes.Equal(got, want) { + t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want) + } + } + + // Same for SHAKE + for alg, df := range testShakes { + want := make([]byte, 16) + got := make([]byte, 16) + d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr)) + + d.Reset() + d.Write(buf) + d.Read(want) + d.Reset() + for i := 0; i < len(buf); { + // Cycle through offsets which make a 137 byte sequence. + // Because 137 is prime this sequence should exercise all corner cases. + offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} + for _, j := range offsets { + if v := len(buf) - i; v < j { + j = v + } + d.Write(buf[i : i+j]) + i += j + } + } + d.Read(got) + if !bytes.Equal(got, want) { + t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want) + } + } +} + +// TestAppend checks that appending works when reallocation is necessary. +func TestAppend(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testAppend) +} + +func testAppend(t *testing.T) { + d := New224() + + for capacity := 2; capacity <= 66; capacity += 64 { + // The first time around the loop, Sum will have to reallocate. + // The second time, it will not. + buf := make([]byte, 2, capacity) + d.Reset() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("got %s, want %s", got, expected) + } + } +} + +// TestAppendNoRealloc tests that appending works when no reallocation is necessary. +func TestAppendNoRealloc(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testAppendNoRealloc) +} + +func testAppendNoRealloc(t *testing.T) { + buf := make([]byte, 1, 200) + d := New224() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("got %s, want %s", got, expected) + } +} + +// TestSqueezing checks that squeezing the full output a single time produces +// the same output as repeatedly squeezing the instance. +func TestSqueezing(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testSqueezing) +} + +func testSqueezing(t *testing.T) { + for algo, v := range testShakes { + d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) + d0.Write([]byte(testString)) + ref := make([]byte, 32) + d0.Read(ref) + + d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) + d1.Write([]byte(testString)) + var multiple []byte + for range ref { + d1.Read(make([]byte, 0)) + one := make([]byte, 1) + d1.Read(one) + multiple = append(multiple, one...) + } + if !bytes.Equal(ref, multiple) { + t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref)) + } + } +} + +// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. +// +// The alignment of each slice is intentionally randomized to detect alignment +// issues in the implementation. See https://golang.org/issue/37644. +// Ideally, the compiler should fuzz the alignment itself. +// (See https://golang.org/issue/35128.) +func sequentialBytes(size int) []byte { + alignmentOffset := rand.Intn(8) + result := make([]byte, size+alignmentOffset)[alignmentOffset:] + for i := range result { + result[i] = byte(i) + } + return result +} + +func TestReset(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testReset) +} + +func testReset(t *testing.T) { + out1 := make([]byte, 32) + out2 := make([]byte, 32) + + for _, v := range testShakes { + // Calculate hash for the first time + c := v.constructor(nil, []byte{0x99, 0x98}) + c.Write(sequentialBytes(0x100)) + c.Read(out1) + + // Calculate hash again + c.Reset() + c.Write(sequentialBytes(0x100)) + c.Read(out2) + + if !bytes.Equal(out1, out2) { + t.Error("\nExpected:\n", out1, "\ngot:\n", out2) + } + } +} + +var sinkSHA3 byte + +func TestAllocations(t *testing.T) { + cryptotest.SkipTestAllocations(t) + t.Run("New", func(t *testing.T) { + if allocs := testing.AllocsPerRun(10, func() { + h := New256() + b := []byte("ABC") + h.Write(b) + out := make([]byte, 0, 32) + out = h.Sum(out) + sinkSHA3 ^= out[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("NewSHAKE", func(t *testing.T) { + if allocs := testing.AllocsPerRun(10, func() { + h := NewSHAKE128() + b := []byte("ABC") + h.Write(b) + out := make([]byte, 32) + h.Read(out) + sinkSHA3 ^= out[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("Sum", func(t *testing.T) { + if allocs := testing.AllocsPerRun(10, func() { + b := []byte("ABC") + out := Sum256(b) + sinkSHA3 ^= out[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("SumSHAKE", func(t *testing.T) { + if allocs := testing.AllocsPerRun(10, func() { + b := []byte("ABC") + out := SumSHAKE128(b, 10) + sinkSHA3 ^= out[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) +} + +func TestCSHAKEAccumulated(t *testing.T) { + // Generated with pycryptodome@3.20.0 + // + // from Crypto.Hash import cSHAKE128 + // rng = cSHAKE128.new() + // acc = cSHAKE128.new() + // for n in range(200): + // N = rng.read(n) + // for s in range(200): + // S = rng.read(s) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(100)) + // acc.update(c.read(200)) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(168)) + // acc.update(c.read(200)) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(200)) + // acc.update(c.read(200)) + // print(acc.read(32).hex()) + // + // and with @noble/hashes@v1.5.0 + // + // import { bytesToHex } from "@noble/hashes/utils"; + // import { cshake128 } from "@noble/hashes/sha3-addons"; + // const rng = cshake128.create(); + // const acc = cshake128.create(); + // for (let n = 0; n < 200; n++) { + // const N = rng.xof(n); + // for (let s = 0; s < 200; s++) { + // const S = rng.xof(s); + // let c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(100)); + // acc.update(c.xof(200)); + // c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(168)); + // acc.update(c.xof(200)); + // c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(200)); + // acc.update(c.xof(200)); + // } + // } + // console.log(bytesToHex(acc.xof(32))); + // + cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) { + t.Run("cSHAKE128", func(t *testing.T) { + testCSHAKEAccumulated(t, NewCSHAKE128, (1600-256)/8, + "bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252") + }) + t.Run("cSHAKE256", func(t *testing.T) { + testCSHAKEAccumulated(t, NewCSHAKE256, (1600-512)/8, + "0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef") + }) + }) +} + +func testCSHAKEAccumulated(t *testing.T, newCSHAKE func(N, S []byte) *SHAKE, rate int64, exp string) { + rnd := newCSHAKE(nil, nil) + acc := newCSHAKE(nil, nil) + for n := 0; n < 200; n++ { + N := make([]byte, n) + rnd.Read(N) + for s := 0; s < 200; s++ { + S := make([]byte, s) + rnd.Read(S) + + c := newCSHAKE(N, S) + io.CopyN(c, rnd, 100 /* < rate */) + io.CopyN(acc, c, 200) + + c.Reset() + io.CopyN(c, rnd, rate) + io.CopyN(acc, c, 200) + + c.Reset() + io.CopyN(c, rnd, 200 /* > rate */) + io.CopyN(acc, c, 200) + } + } + out := make([]byte, 32) + acc.Read(out) + if got := hex.EncodeToString(out); got != exp { + t.Errorf("got %s, want %s", got, exp) + } +} + +func TestCSHAKELargeS(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", testCSHAKELargeS) +} + +func testCSHAKELargeS(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + // See https://go.dev/issue/66232. + const s = (1<<32)/8 + 1000 // s * 8 > 2^32 + S := make([]byte, s) + rnd := NewSHAKE128() + rnd.Read(S) + c := NewCSHAKE128(nil, S) + io.CopyN(c, rnd, 1000) + out := make([]byte, 32) + c.Read(out) + + // Generated with pycryptodome@3.20.0 + // + // from Crypto.Hash import cSHAKE128 + // rng = cSHAKE128.new() + // S = rng.read(536871912) + // c = cSHAKE128.new(custom=S) + // c.update(rng.read(1000)) + // print(c.read(32).hex()) + // + exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0" + if got := hex.EncodeToString(out); got != exp { + t.Errorf("got %s, want %s", got, exp) + } +} + +func TestMarshalUnmarshal(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) { + t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) }) + t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) }) + t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) }) + t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) }) + t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE128()) }) + t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE256()) }) + t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE128([]byte("N"), []byte("S"))) }) + t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE256([]byte("N"), []byte("S"))) }) + }) +} + +// TODO(filippo): move this to crypto/internal/cryptotest. +func testMarshalUnmarshal(t *testing.T, h *SHA3) { + buf := make([]byte, 200) + rand.Read(buf) + n := rand.Intn(200) + h.Write(buf) + want := h.Sum(nil) + h.Reset() + h.Write(buf[:n]) + b, err := h.MarshalBinary() + if err != nil { + t.Errorf("MarshalBinary: %v", err) + } + h.Write(bytes.Repeat([]byte{0}, 200)) + if err := h.UnmarshalBinary(b); err != nil { + t.Errorf("UnmarshalBinary: %v", err) + } + h.Write(buf[n:]) + got := h.Sum(nil) + if !bytes.Equal(got, want) { + t.Errorf("got %x, want %x", got, want) + } +} + +// TODO(filippo): move this to crypto/internal/cryptotest. +func testMarshalUnmarshalSHAKE(t *testing.T, h *SHAKE) { + buf := make([]byte, 200) + rand.Read(buf) + n := rand.Intn(200) + h.Write(buf) + want := make([]byte, 32) + h.Read(want) + h.Reset() + h.Write(buf[:n]) + b, err := h.MarshalBinary() + if err != nil { + t.Errorf("MarshalBinary: %v", err) + } + h.Write(bytes.Repeat([]byte{0}, 200)) + if err := h.UnmarshalBinary(b); err != nil { + t.Errorf("UnmarshalBinary: %v", err) + } + h.Write(buf[n:]) + got := make([]byte, 32) + h.Read(got) + if !bytes.Equal(got, want) { + t.Errorf("got %x, want %x", got, want) + } +} + +// benchmarkHash tests the speed to hash num buffers of buflen each. +func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { + b.StopTimer() + h.Reset() + data := sequentialBytes(size) + b.SetBytes(int64(size * num)) + b.StartTimer() + + var state []byte + for i := 0; i < b.N; i++ { + for j := 0; j < num; j++ { + h.Write(data) + } + state = h.Sum(state[:0]) + } + b.StopTimer() + h.Reset() +} + +// benchmarkShake is specialized to the Shake instances, which don't +// require a copy on reading output. +func benchmarkShake(b *testing.B, h *SHAKE, size, num int) { + b.StopTimer() + h.Reset() + data := sequentialBytes(size) + d := make([]byte, 32) + + b.SetBytes(int64(size * num)) + b.StartTimer() + + for i := 0; i < b.N; i++ { + h.Reset() + for j := 0; j < num; j++ { + h.Write(data) + } + h.Read(d) + } +} + +func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } +func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } +func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } +func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } + +func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewSHAKE128(), 1350, 1) } +func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 1350, 1) } +func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 16, 1024) } +func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 1024, 1024) } + +func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } diff --git a/crypto/sha512/_asm/go.mod b/crypto/sha512/_asm/go.mod deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/sha512/_asm/go.sum b/crypto/sha512/_asm/go.sum deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/sha512/fallback_test.go b/crypto/sha512/fallback_test.go deleted file mode 100644 index b55a4a56fa9..00000000000 --- a/crypto/sha512/fallback_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build s390x && !purego - -package sha512 - -import ( - "fmt" - "io" - "testing" -) - -// Tests the fallback code path in case the optimized asm -// implementation cannot be used. -// See also TestBlockGeneric. -func TestGenericPath(t *testing.T) { - if !useAsm { - t.Skipf("assembly implementation unavailable") - } - useAsm = false - defer func() { useAsm = true }() - c := New() - in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" - gold := "6922e319366d677f34c504af31bfcb29" + - "e531c125ecd08679362bffbd6b6ebfb9" + - "0dcc27dfc1f3d3b16a16c0763cf43b91" + - "40bbf9bbb7233724e9a0c6655b185d76" - if _, err := io.WriteString(c, in); err != nil { - t.Fatalf("could not write to c: %v", err) - } - out := fmt.Sprintf("%x", c.Sum(nil)) - if out != gold { - t.Fatalf("mismatch: got %s, wanted %s", out, gold) - } -} diff --git a/crypto/sha512/sha512.go b/crypto/sha512/sha512.go index 9721b953b90..92d79a8312f 100644 --- a/crypto/sha512/sha512.go +++ b/crypto/sha512/sha512.go @@ -11,12 +11,11 @@ package sha512 import ( - "errors" - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/internal/boring" - "github.com/runZeroInc/excrypto/internal/byteorder" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/sha512" ) func init() { @@ -44,167 +43,6 @@ const ( BlockSize = 128 ) -const ( - chunk = 128 - init0 = 0x6a09e667f3bcc908 - init1 = 0xbb67ae8584caa73b - init2 = 0x3c6ef372fe94f82b - init3 = 0xa54ff53a5f1d36f1 - init4 = 0x510e527fade682d1 - init5 = 0x9b05688c2b3e6c1f - init6 = 0x1f83d9abfb41bd6b - init7 = 0x5be0cd19137e2179 - init0_224 = 0x8c3d37c819544da2 - init1_224 = 0x73e1996689dcd4d6 - init2_224 = 0x1dfab7ae32ff9c82 - init3_224 = 0x679dd514582f9fcf - init4_224 = 0x0f6d2b697bd44da8 - init5_224 = 0x77e36f7304c48942 - init6_224 = 0x3f9d85a86a1d36c8 - init7_224 = 0x1112e6ad91d692a1 - init0_256 = 0x22312194fc2bf72c - init1_256 = 0x9f555fa3c84c64c2 - init2_256 = 0x2393b86b6f53b151 - init3_256 = 0x963877195940eabd - init4_256 = 0x96283ee2a88effe3 - init5_256 = 0xbe5e1e2553863992 - init6_256 = 0x2b0199fc2c85b8aa - init7_256 = 0x0eb72ddc81c52ca2 - init0_384 = 0xcbbb9d5dc1059ed8 - init1_384 = 0x629a292a367cd507 - init2_384 = 0x9159015a3070dd17 - init3_384 = 0x152fecd8f70e5939 - init4_384 = 0x67332667ffc00b31 - init5_384 = 0x8eb44a8768581511 - init6_384 = 0xdb0c2e0d64f98fa7 - init7_384 = 0x47b5481dbefa4fa4 -) - -// digest represents the partial evaluation of a checksum. -type digest struct { - h [8]uint64 - x [chunk]byte - nx int - len uint64 - function crypto.Hash -} - -func (d *digest) Reset() { - switch d.function { - case crypto.SHA384: - d.h[0] = init0_384 - d.h[1] = init1_384 - d.h[2] = init2_384 - d.h[3] = init3_384 - d.h[4] = init4_384 - d.h[5] = init5_384 - d.h[6] = init6_384 - d.h[7] = init7_384 - case crypto.SHA512_224: - d.h[0] = init0_224 - d.h[1] = init1_224 - d.h[2] = init2_224 - d.h[3] = init3_224 - d.h[4] = init4_224 - d.h[5] = init5_224 - d.h[6] = init6_224 - d.h[7] = init7_224 - case crypto.SHA512_256: - d.h[0] = init0_256 - d.h[1] = init1_256 - d.h[2] = init2_256 - d.h[3] = init3_256 - d.h[4] = init4_256 - d.h[5] = init5_256 - d.h[6] = init6_256 - d.h[7] = init7_256 - default: - d.h[0] = init0 - d.h[1] = init1 - d.h[2] = init2 - d.h[3] = init3 - d.h[4] = init4 - d.h[5] = init5 - d.h[6] = init6 - d.h[7] = init7 - } - d.nx = 0 - d.len = 0 -} - -const ( - magic384 = "sha\x04" - magic512_224 = "sha\x05" - magic512_256 = "sha\x06" - magic512 = "sha\x07" - marshaledSize = len(magic512) + 8*8 + chunk + 8 -) - -func (d *digest) MarshalBinary() ([]byte, error) { - return d.AppendBinary(make([]byte, 0, marshaledSize)) -} - -func (d *digest) AppendBinary(b []byte) ([]byte, error) { - switch d.function { - case crypto.SHA384: - b = append(b, magic384...) - case crypto.SHA512_224: - b = append(b, magic512_224...) - case crypto.SHA512_256: - b = append(b, magic512_256...) - case crypto.SHA512: - b = append(b, magic512...) - default: - return nil, errors.New("crypto/sha512: invalid hash function") - } - b = byteorder.BeAppendUint64(b, d.h[0]) - b = byteorder.BeAppendUint64(b, d.h[1]) - b = byteorder.BeAppendUint64(b, d.h[2]) - b = byteorder.BeAppendUint64(b, d.h[3]) - b = byteorder.BeAppendUint64(b, d.h[4]) - b = byteorder.BeAppendUint64(b, d.h[5]) - b = byteorder.BeAppendUint64(b, d.h[6]) - b = byteorder.BeAppendUint64(b, d.h[7]) - b = append(b, d.x[:d.nx]...) - b = append(b, make([]byte, len(d.x)-d.nx)...) - b = byteorder.BeAppendUint64(b, d.len) - return b, nil -} - -func (d *digest) UnmarshalBinary(b []byte) error { - if len(b) < len(magic512) { - return errors.New("crypto/sha512: invalid hash state identifier") - } - switch { - case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384: - case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224: - case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256: - case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512: - default: - return errors.New("crypto/sha512: invalid hash state identifier") - } - if len(b) != marshaledSize { - return errors.New("crypto/sha512: invalid hash state size") - } - b = b[len(magic512):] - b, d.h[0] = consumeUint64(b) - b, d.h[1] = consumeUint64(b) - b, d.h[2] = consumeUint64(b) - b, d.h[3] = consumeUint64(b) - b, d.h[4] = consumeUint64(b) - b, d.h[5] = consumeUint64(b) - b, d.h[6] = consumeUint64(b) - b, d.h[7] = consumeUint64(b) - b = b[copy(d.x[:], b):] - b, d.len = consumeUint64(b) - d.nx = int(d.len % chunk) - return nil -} - -func consumeUint64(b []byte) ([]byte, uint64) { - return b[8:], byteorder.BeUint64(b) -} - // New returns a new [hash.Hash] computing the SHA-512 checksum. The Hash // also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal @@ -213,9 +51,7 @@ func New() hash.Hash { if boring.Enabled { return boring.NewSHA512() } - d := &digest{function: crypto.SHA512} - d.Reset() - return d + return sha512.New() } // New512_224 returns a new [hash.Hash] computing the SHA-512/224 checksum. The Hash @@ -223,9 +59,7 @@ func New() hash.Hash { // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. func New512_224() hash.Hash { - d := &digest{function: crypto.SHA512_224} - d.Reset() - return d + return sha512.New512_224() } // New512_256 returns a new [hash.Hash] computing the SHA-512/256 checksum. The Hash @@ -233,123 +67,18 @@ func New512_224() hash.Hash { // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. func New512_256() hash.Hash { - d := &digest{function: crypto.SHA512_256} - d.Reset() - return d + return sha512.New512_256() } // New384 returns a new [hash.Hash] computing the SHA-384 checksum. The Hash -// also implements [encoding.BinaryMarshaler], [encoding.AppendBinary] and +// also implements [encoding.BinaryMarshaler], [encoding.BinaryAppender] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. func New384() hash.Hash { if boring.Enabled { return boring.NewSHA384() } - d := &digest{function: crypto.SHA384} - d.Reset() - return d -} - -func (d *digest) Size() int { - switch d.function { - case crypto.SHA512_224: - return Size224 - case crypto.SHA512_256: - return Size256 - case crypto.SHA384: - return Size384 - default: - return Size - } -} - -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Write(p []byte) (nn int, err error) { - if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 { - boring.Unreachable() - } - nn = len(p) - d.len += uint64(nn) - if d.nx > 0 { - n := copy(d.x[d.nx:], p) - d.nx += n - if d.nx == chunk { - block(d, d.x[:]) - d.nx = 0 - } - p = p[n:] - } - if len(p) >= chunk { - n := len(p) &^ (chunk - 1) - block(d, p[:n]) - p = p[n:] - } - if len(p) > 0 { - d.nx = copy(d.x[:], p) - } - return -} - -func (d *digest) Sum(in []byte) []byte { - if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 { - boring.Unreachable() - } - // Make a copy of d so that caller can keep writing and summing. - d0 := new(digest) - *d0 = *d - hash := d0.checkSum() - switch d0.function { - case crypto.SHA384: - return append(in, hash[:Size384]...) - case crypto.SHA512_224: - return append(in, hash[:Size224]...) - case crypto.SHA512_256: - return append(in, hash[:Size256]...) - default: - return append(in, hash[:]...) - } -} - -func (d *digest) checkSum() [Size]byte { - // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. - len := d.len - var tmp [128 + 16]byte // padding + length buffer - tmp[0] = 0x80 - var t uint64 - if len%128 < 112 { - t = 112 - len%128 - } else { - t = 128 + 112 - len%128 - } - - // Length in bits. - len <<= 3 - padlen := tmp[:t+16] - // Upper 64 bits are always zero, because len variable has type uint64, - // and tmp is already zeroed at that index, so we can skip updating it. - // byteorder.BePutUint64(padlen[t+0:], 0) - byteorder.BePutUint64(padlen[t+8:], len) - d.Write(padlen) - - if d.nx != 0 { - panic("d.nx != 0") - } - - var digest [Size]byte - byteorder.BePutUint64(digest[0:], d.h[0]) - byteorder.BePutUint64(digest[8:], d.h[1]) - byteorder.BePutUint64(digest[16:], d.h[2]) - byteorder.BePutUint64(digest[24:], d.h[3]) - byteorder.BePutUint64(digest[32:], d.h[4]) - byteorder.BePutUint64(digest[40:], d.h[5]) - if d.function != crypto.SHA384 { - byteorder.BePutUint64(digest[48:], d.h[6]) - byteorder.BePutUint64(digest[56:], d.h[7]) - } - - return digest + return sha512.New384() } // Sum512 returns the SHA512 checksum of the data. @@ -357,10 +86,11 @@ func Sum512(data []byte) [Size]byte { if boring.Enabled { return boring.SHA512(data) } - d := digest{function: crypto.SHA512} - d.Reset() - d.Write(data) - return d.checkSum() + h := New() + h.Write(data) + var sum [Size]byte + h.Sum(sum[:0]) + return sum } // Sum384 returns the SHA384 checksum of the data. @@ -368,30 +98,27 @@ func Sum384(data []byte) [Size384]byte { if boring.Enabled { return boring.SHA384(data) } - d := digest{function: crypto.SHA384} - d.Reset() - d.Write(data) - sum := d.checkSum() - ap := (*[Size384]byte)(sum[:]) - return *ap + h := New384() + h.Write(data) + var sum [Size384]byte + h.Sum(sum[:0]) + return sum } // Sum512_224 returns the Sum512/224 checksum of the data. func Sum512_224(data []byte) [Size224]byte { - d := digest{function: crypto.SHA512_224} - d.Reset() - d.Write(data) - sum := d.checkSum() - ap := (*[Size224]byte)(sum[:]) - return *ap + h := New512_224() + h.Write(data) + var sum [Size224]byte + h.Sum(sum[:0]) + return sum } // Sum512_256 returns the Sum512/256 checksum of the data. func Sum512_256(data []byte) [Size256]byte { - d := digest{function: crypto.SHA512_256} - d.Reset() - d.Write(data) - sum := d.checkSum() - ap := (*[Size256]byte)(sum[:]) - return *ap + h := New512_256() + h.Write(data) + var sum [Size256]byte + h.Sum(sum[:0]) + return sum } diff --git a/crypto/sha512/sha512_test.go b/crypto/sha512/sha512_test.go index 7773d344926..5d34a647774 100644 --- a/crypto/sha512/sha512_test.go +++ b/crypto/sha512/sha512_test.go @@ -8,17 +8,15 @@ package sha512 import ( "bytes" + "encoding" "encoding/hex" "fmt" - "hash" "io" "testing" - "crypto/rand" + "github.com/runZeroInc/excrypto/hash" - "github.com/runZeroInc/excrypto/crypto/internal/boring" "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" - "github.com/runZeroInc/excrypto/encoding" ) type sha512Test struct { @@ -682,6 +680,12 @@ func testHash(t *testing.T, name, in, outHex string, oneShotResult []byte, diges } func TestGolden(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + testGolden(t) + }) +} + +func testGolden(t *testing.T) { tests := []struct { name string oneShotHash func(in []byte) []byte @@ -722,6 +726,12 @@ func TestGolden(t *testing.T) { } func TestGoldenMarshal(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + testGoldenMarshal(t) + }) +} + +func testGoldenMarshal(t *testing.T) { tests := []struct { name string newHash func() hash.Hash @@ -836,21 +846,6 @@ func TestBlockSize(t *testing.T) { } } -// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. -func TestBlockGeneric(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't expose digest") - } - gen, asm := New().(*digest), New().(*digest) - buf := make([]byte, BlockSize*20) // arbitrary factor - rand.Read(buf) - blockGeneric(gen, buf) - block(asm, buf) - if *gen != *asm { - t.Error("block and blockGeneric resulted in different states") - } -} - // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums @@ -908,37 +903,102 @@ func TestLargeHashes(t *testing.T) { } func TestAllocations(t *testing.T) { - if boring.Enabled { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } - in := []byte("hello, world!") - out := make([]byte, 0, Size) - h := New() - n := int(testing.AllocsPerRun(10, func() { - h.Reset() - h.Write(in) - out = h.Sum(out[:0]) - })) - if n > 0 { - t.Errorf("allocs = %d, want 0", n) + cryptotest.SkipTestAllocations(t) + if n := testing.AllocsPerRun(10, func() { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + + { + h := New() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + { + h := New512_224() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + { + h := New512_256() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + { + h := New384() + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + } + + Sum512(in) + Sum384(in) + Sum512_224(in) + Sum512_256(in) + }); n > 0 { + t.Errorf("allocs = %v, want 0", n) } } -func TestSHA512Hash(t *testing.T) { +func TestHash(t *testing.T) { t.Run("SHA-384", func(t *testing.T) { - cryptotest.TestHash(t, New384) + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + cryptotest.TestHash(t, New384) + }) }) t.Run("SHA-512/224", func(t *testing.T) { - cryptotest.TestHash(t, New512_224) + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + cryptotest.TestHash(t, New512_224) + }) }) t.Run("SHA-512/256", func(t *testing.T) { - cryptotest.TestHash(t, New512_256) + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + cryptotest.TestHash(t, New512_256) + }) }) t.Run("SHA-512", func(t *testing.T) { - cryptotest.TestHash(t, New) + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + cryptotest.TestHash(t, New) + }) }) } +func TestExtraMethods(t *testing.T) { + t.Run("SHA-384", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + h := maybeCloner(New384()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) + t.Run("SHA-512/224", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + h := maybeCloner(New512_224()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) + t.Run("SHA-512/256", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + h := maybeCloner(New512_256()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) + t.Run("SHA-512", func(t *testing.T) { + cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) { + h := maybeCloner(New()) + cryptotest.NoExtraMethods(t, h, "MarshalBinary", "UnmarshalBinary", "AppendBinary") + }) + }) +} + +func maybeCloner(h hash.Hash) any { + if c, ok := h.(hash.Cloner); ok { + return &c + } + return &h +} + var bench = New() var buf = make([]byte, 8192) diff --git a/crypto/sha512/sha512block_amd64.go b/crypto/sha512/sha512block_amd64.go deleted file mode 100644 index ee100ec52f2..00000000000 --- a/crypto/sha512/sha512block_amd64.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha512 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -//go:noescape -func blockAVX2(dig *digest, p []byte) - -//go:noescape -func blockAMD64(dig *digest, p []byte) - -var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 - -func block(dig *digest, p []byte) { - if useAVX2 { - blockAVX2(dig, p) - } else { - blockAMD64(dig, p) - } -} diff --git a/crypto/sha512/sha512block_amd64.s b/crypto/sha512/sha512block_amd64.s deleted file mode 100644 index fdcef222150..00000000000 --- a/crypto/sha512/sha512block_amd64.s +++ /dev/null @@ -1,5398 +0,0 @@ -// Code generated by command: go run sha512block_amd64_asm.go -out ../sha512block_amd64.s -pkg sha512. DO NOT EDIT. - -//go:build !purego - -#include "textflag.h" - -// func blockAMD64(dig *digest, p []byte) -TEXT ·blockAMD64(SB), $648-32 - MOVQ p_base+8(FP), SI - MOVQ p_len+16(FP), DX - SHRQ $0x07, DX - SHLQ $0x07, DX - LEAQ (SI)(DX*1), DI - MOVQ DI, 640(SP) - CMPQ SI, DI - JEQ end - MOVQ dig+0(FP), BP - MOVQ (BP), R8 - MOVQ 8(BP), R9 - MOVQ 16(BP), R10 - MOVQ 24(BP), R11 - MOVQ 32(BP), R12 - MOVQ 40(BP), R13 - MOVQ 48(BP), R14 - MOVQ 56(BP), R15 - -loop: - MOVQ SP, BP - MOVQ (SI), AX - BSWAPQ AX - MOVQ AX, (BP) - MOVQ $0x428a2f98d728ae22, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 8(SI), AX - BSWAPQ AX - MOVQ AX, 8(BP) - MOVQ $0x7137449123ef65cd, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 16(SI), AX - BSWAPQ AX - MOVQ AX, 16(BP) - MOVQ $0xb5c0fbcfec4d3b2f, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 24(SI), AX - BSWAPQ AX - MOVQ AX, 24(BP) - MOVQ $0xe9b5dba58189dbbc, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 32(SI), AX - BSWAPQ AX - MOVQ AX, 32(BP) - MOVQ $0x3956c25bf348b538, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 40(SI), AX - BSWAPQ AX - MOVQ AX, 40(BP) - MOVQ $0x59f111f1b605d019, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 48(SI), AX - BSWAPQ AX - MOVQ AX, 48(BP) - MOVQ $0x923f82a4af194f9b, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 56(SI), AX - BSWAPQ AX - MOVQ AX, 56(BP) - MOVQ $0xab1c5ed5da6d8118, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 64(SI), AX - BSWAPQ AX - MOVQ AX, 64(BP) - MOVQ $0xd807aa98a3030242, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 72(SI), AX - BSWAPQ AX - MOVQ AX, 72(BP) - MOVQ $0x12835b0145706fbe, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 80(SI), AX - BSWAPQ AX - MOVQ AX, 80(BP) - MOVQ $0x243185be4ee4b28c, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 88(SI), AX - BSWAPQ AX - MOVQ AX, 88(BP) - MOVQ $0x550c7dc3d5ffb4e2, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 96(SI), AX - BSWAPQ AX - MOVQ AX, 96(BP) - MOVQ $0x72be5d74f27b896f, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 104(SI), AX - BSWAPQ AX - MOVQ AX, 104(BP) - MOVQ $0x80deb1fe3b1696b1, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 112(SI), AX - BSWAPQ AX - MOVQ AX, 112(BP) - MOVQ $0x9bdc06a725c71235, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 120(SI), AX - BSWAPQ AX - MOVQ AX, 120(BP) - MOVQ $0xc19bf174cf692694, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 112(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 8(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 72(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ (BP), BX - ADDQ BX, AX - MOVQ AX, 128(BP) - MOVQ $0xe49b69c19ef14ad2, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 120(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 16(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 80(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 8(BP), BX - ADDQ BX, AX - MOVQ AX, 136(BP) - MOVQ $0xefbe4786384f25e3, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 128(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 24(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 88(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 16(BP), BX - ADDQ BX, AX - MOVQ AX, 144(BP) - MOVQ $0x0fc19dc68b8cd5b5, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 136(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 32(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 96(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 24(BP), BX - ADDQ BX, AX - MOVQ AX, 152(BP) - MOVQ $0x240ca1cc77ac9c65, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 144(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 40(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 104(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 32(BP), BX - ADDQ BX, AX - MOVQ AX, 160(BP) - MOVQ $0x2de92c6f592b0275, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 152(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 48(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 112(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 40(BP), BX - ADDQ BX, AX - MOVQ AX, 168(BP) - MOVQ $0x4a7484aa6ea6e483, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 160(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 56(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 120(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 48(BP), BX - ADDQ BX, AX - MOVQ AX, 176(BP) - MOVQ $0x5cb0a9dcbd41fbd4, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 168(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 64(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 128(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 56(BP), BX - ADDQ BX, AX - MOVQ AX, 184(BP) - MOVQ $0x76f988da831153b5, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 176(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 72(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 136(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 64(BP), BX - ADDQ BX, AX - MOVQ AX, 192(BP) - MOVQ $0x983e5152ee66dfab, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 184(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 80(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 144(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 72(BP), BX - ADDQ BX, AX - MOVQ AX, 200(BP) - MOVQ $0xa831c66d2db43210, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 192(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 88(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 152(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 80(BP), BX - ADDQ BX, AX - MOVQ AX, 208(BP) - MOVQ $0xb00327c898fb213f, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 200(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 96(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 160(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 88(BP), BX - ADDQ BX, AX - MOVQ AX, 216(BP) - MOVQ $0xbf597fc7beef0ee4, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 208(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 104(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 168(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 96(BP), BX - ADDQ BX, AX - MOVQ AX, 224(BP) - MOVQ $0xc6e00bf33da88fc2, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 216(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 112(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 176(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 104(BP), BX - ADDQ BX, AX - MOVQ AX, 232(BP) - MOVQ $0xd5a79147930aa725, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 224(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 120(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 184(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 112(BP), BX - ADDQ BX, AX - MOVQ AX, 240(BP) - MOVQ $0x06ca6351e003826f, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 232(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 128(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 192(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 120(BP), BX - ADDQ BX, AX - MOVQ AX, 248(BP) - MOVQ $0x142929670a0e6e70, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 240(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 136(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 200(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 128(BP), BX - ADDQ BX, AX - MOVQ AX, 256(BP) - MOVQ $0x27b70a8546d22ffc, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 248(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 144(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 208(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 136(BP), BX - ADDQ BX, AX - MOVQ AX, 264(BP) - MOVQ $0x2e1b21385c26c926, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 256(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 152(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 216(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 144(BP), BX - ADDQ BX, AX - MOVQ AX, 272(BP) - MOVQ $0x4d2c6dfc5ac42aed, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 264(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 160(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 224(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 152(BP), BX - ADDQ BX, AX - MOVQ AX, 280(BP) - MOVQ $0x53380d139d95b3df, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 272(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 168(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 232(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 160(BP), BX - ADDQ BX, AX - MOVQ AX, 288(BP) - MOVQ $0x650a73548baf63de, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 280(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 176(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 240(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 168(BP), BX - ADDQ BX, AX - MOVQ AX, 296(BP) - MOVQ $0x766a0abb3c77b2a8, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 288(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 184(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 248(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 176(BP), BX - ADDQ BX, AX - MOVQ AX, 304(BP) - MOVQ $0x81c2c92e47edaee6, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 296(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 192(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 256(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 184(BP), BX - ADDQ BX, AX - MOVQ AX, 312(BP) - MOVQ $0x92722c851482353b, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 304(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 200(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 264(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 192(BP), BX - ADDQ BX, AX - MOVQ AX, 320(BP) - MOVQ $0xa2bfe8a14cf10364, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 312(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 208(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 272(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 200(BP), BX - ADDQ BX, AX - MOVQ AX, 328(BP) - MOVQ $0xa81a664bbc423001, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 320(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 216(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 280(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 208(BP), BX - ADDQ BX, AX - MOVQ AX, 336(BP) - MOVQ $0xc24b8b70d0f89791, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 328(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 224(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 288(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 216(BP), BX - ADDQ BX, AX - MOVQ AX, 344(BP) - MOVQ $0xc76c51a30654be30, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 336(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 232(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 296(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 224(BP), BX - ADDQ BX, AX - MOVQ AX, 352(BP) - MOVQ $0xd192e819d6ef5218, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 344(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 240(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 304(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 232(BP), BX - ADDQ BX, AX - MOVQ AX, 360(BP) - MOVQ $0xd69906245565a910, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 352(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 248(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 312(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 240(BP), BX - ADDQ BX, AX - MOVQ AX, 368(BP) - MOVQ $0xf40e35855771202a, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 360(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 256(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 320(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 248(BP), BX - ADDQ BX, AX - MOVQ AX, 376(BP) - MOVQ $0x106aa07032bbd1b8, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 368(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 264(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 328(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 256(BP), BX - ADDQ BX, AX - MOVQ AX, 384(BP) - MOVQ $0x19a4c116b8d2d0c8, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 376(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 272(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 336(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 264(BP), BX - ADDQ BX, AX - MOVQ AX, 392(BP) - MOVQ $0x1e376c085141ab53, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 384(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 280(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 344(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 272(BP), BX - ADDQ BX, AX - MOVQ AX, 400(BP) - MOVQ $0x2748774cdf8eeb99, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 392(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 288(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 352(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 280(BP), BX - ADDQ BX, AX - MOVQ AX, 408(BP) - MOVQ $0x34b0bcb5e19b48a8, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 400(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 296(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 360(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 288(BP), BX - ADDQ BX, AX - MOVQ AX, 416(BP) - MOVQ $0x391c0cb3c5c95a63, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 408(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 304(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 368(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 296(BP), BX - ADDQ BX, AX - MOVQ AX, 424(BP) - MOVQ $0x4ed8aa4ae3418acb, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 416(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 312(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 376(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 304(BP), BX - ADDQ BX, AX - MOVQ AX, 432(BP) - MOVQ $0x5b9cca4f7763e373, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 424(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 320(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 384(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 312(BP), BX - ADDQ BX, AX - MOVQ AX, 440(BP) - MOVQ $0x682e6ff3d6b2b8a3, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 432(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 328(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 392(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 320(BP), BX - ADDQ BX, AX - MOVQ AX, 448(BP) - MOVQ $0x748f82ee5defb2fc, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 440(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 336(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 400(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 328(BP), BX - ADDQ BX, AX - MOVQ AX, 456(BP) - MOVQ $0x78a5636f43172f60, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 448(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 344(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 408(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 336(BP), BX - ADDQ BX, AX - MOVQ AX, 464(BP) - MOVQ $0x84c87814a1f0ab72, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 456(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 352(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 416(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 344(BP), BX - ADDQ BX, AX - MOVQ AX, 472(BP) - MOVQ $0x8cc702081a6439ec, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 464(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 360(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 424(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 352(BP), BX - ADDQ BX, AX - MOVQ AX, 480(BP) - MOVQ $0x90befffa23631e28, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 472(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 368(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 432(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 360(BP), BX - ADDQ BX, AX - MOVQ AX, 488(BP) - MOVQ $0xa4506cebde82bde9, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 480(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 376(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 440(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 368(BP), BX - ADDQ BX, AX - MOVQ AX, 496(BP) - MOVQ $0xbef9a3f7b2c67915, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 488(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 384(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 448(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 376(BP), BX - ADDQ BX, AX - MOVQ AX, 504(BP) - MOVQ $0xc67178f2e372532b, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 496(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 392(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 456(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 384(BP), BX - ADDQ BX, AX - MOVQ AX, 512(BP) - MOVQ $0xca273eceea26619c, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 504(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 400(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 464(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 392(BP), BX - ADDQ BX, AX - MOVQ AX, 520(BP) - MOVQ $0xd186b8c721c0c207, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 512(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 408(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 472(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 400(BP), BX - ADDQ BX, AX - MOVQ AX, 528(BP) - MOVQ $0xeada7dd6cde0eb1e, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 520(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 416(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 480(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 408(BP), BX - ADDQ BX, AX - MOVQ AX, 536(BP) - MOVQ $0xf57d4f7fee6ed178, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 528(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 424(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 488(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 416(BP), BX - ADDQ BX, AX - MOVQ AX, 544(BP) - MOVQ $0x06f067aa72176fba, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 536(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 432(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 496(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 424(BP), BX - ADDQ BX, AX - MOVQ AX, 552(BP) - MOVQ $0x0a637dc5a2c898a6, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 544(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 440(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 504(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 432(BP), BX - ADDQ BX, AX - MOVQ AX, 560(BP) - MOVQ $0x113f9804bef90dae, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 552(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 448(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 512(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 440(BP), BX - ADDQ BX, AX - MOVQ AX, 568(BP) - MOVQ $0x1b710b35131c471b, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ 560(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 456(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 520(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 448(BP), BX - ADDQ BX, AX - MOVQ AX, 576(BP) - MOVQ $0x28db77f523047d84, DX - ADDQ AX, R15 - MOVQ R12, AX - ADDQ DX, R15 - MOVQ R12, CX - RORQ $0x0e, AX - MOVQ R12, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R12, CX - RORQ $0x29, DX - ANDQ R13, CX - XORQ AX, DX - MOVQ R12, AX - NOTQ AX - ADDQ DX, R15 - ANDQ R14, AX - XORQ CX, AX - ADDQ R15, AX - MOVQ R8, DI - MOVQ R10, BX - RORQ $0x1c, DI - MOVQ R8, DX - ANDQ R9, BX - RORQ $0x22, DX - MOVQ R8, CX - ANDQ R10, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R8, DX - MOVQ R9, CX - RORQ $0x27, DX - ANDQ R8, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R15 - ADDQ AX, R11 - ADDQ AX, R15 - MOVQ 568(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 464(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 528(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 456(BP), BX - ADDQ BX, AX - MOVQ AX, 584(BP) - MOVQ $0x32caab7b40c72493, DX - ADDQ AX, R14 - MOVQ R11, AX - ADDQ DX, R14 - MOVQ R11, CX - RORQ $0x0e, AX - MOVQ R11, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R11, CX - RORQ $0x29, DX - ANDQ R12, CX - XORQ AX, DX - MOVQ R11, AX - NOTQ AX - ADDQ DX, R14 - ANDQ R13, AX - XORQ CX, AX - ADDQ R14, AX - MOVQ R15, DI - MOVQ R9, BX - RORQ $0x1c, DI - MOVQ R15, DX - ANDQ R8, BX - RORQ $0x22, DX - MOVQ R15, CX - ANDQ R9, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R15, DX - MOVQ R8, CX - RORQ $0x27, DX - ANDQ R15, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R14 - ADDQ AX, R10 - ADDQ AX, R14 - MOVQ 576(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 472(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 536(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 464(BP), BX - ADDQ BX, AX - MOVQ AX, 592(BP) - MOVQ $0x3c9ebe0a15c9bebc, DX - ADDQ AX, R13 - MOVQ R10, AX - ADDQ DX, R13 - MOVQ R10, CX - RORQ $0x0e, AX - MOVQ R10, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R10, CX - RORQ $0x29, DX - ANDQ R11, CX - XORQ AX, DX - MOVQ R10, AX - NOTQ AX - ADDQ DX, R13 - ANDQ R12, AX - XORQ CX, AX - ADDQ R13, AX - MOVQ R14, DI - MOVQ R8, BX - RORQ $0x1c, DI - MOVQ R14, DX - ANDQ R15, BX - RORQ $0x22, DX - MOVQ R14, CX - ANDQ R8, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R14, DX - MOVQ R15, CX - RORQ $0x27, DX - ANDQ R14, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R13 - ADDQ AX, R9 - ADDQ AX, R13 - MOVQ 584(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 480(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 544(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 472(BP), BX - ADDQ BX, AX - MOVQ AX, 600(BP) - MOVQ $0x431d67c49c100d4c, DX - ADDQ AX, R12 - MOVQ R9, AX - ADDQ DX, R12 - MOVQ R9, CX - RORQ $0x0e, AX - MOVQ R9, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R9, CX - RORQ $0x29, DX - ANDQ R10, CX - XORQ AX, DX - MOVQ R9, AX - NOTQ AX - ADDQ DX, R12 - ANDQ R11, AX - XORQ CX, AX - ADDQ R12, AX - MOVQ R13, DI - MOVQ R15, BX - RORQ $0x1c, DI - MOVQ R13, DX - ANDQ R14, BX - RORQ $0x22, DX - MOVQ R13, CX - ANDQ R15, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R13, DX - MOVQ R14, CX - RORQ $0x27, DX - ANDQ R13, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R12 - ADDQ AX, R8 - ADDQ AX, R12 - MOVQ 592(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 488(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 552(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 480(BP), BX - ADDQ BX, AX - MOVQ AX, 608(BP) - MOVQ $0x4cc5d4becb3e42b6, DX - ADDQ AX, R11 - MOVQ R8, AX - ADDQ DX, R11 - MOVQ R8, CX - RORQ $0x0e, AX - MOVQ R8, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R8, CX - RORQ $0x29, DX - ANDQ R9, CX - XORQ AX, DX - MOVQ R8, AX - NOTQ AX - ADDQ DX, R11 - ANDQ R10, AX - XORQ CX, AX - ADDQ R11, AX - MOVQ R12, DI - MOVQ R14, BX - RORQ $0x1c, DI - MOVQ R12, DX - ANDQ R13, BX - RORQ $0x22, DX - MOVQ R12, CX - ANDQ R14, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R12, DX - MOVQ R13, CX - RORQ $0x27, DX - ANDQ R12, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R11 - ADDQ AX, R15 - ADDQ AX, R11 - MOVQ 600(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 496(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 560(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 488(BP), BX - ADDQ BX, AX - MOVQ AX, 616(BP) - MOVQ $0x597f299cfc657e2a, DX - ADDQ AX, R10 - MOVQ R15, AX - ADDQ DX, R10 - MOVQ R15, CX - RORQ $0x0e, AX - MOVQ R15, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R15, CX - RORQ $0x29, DX - ANDQ R8, CX - XORQ AX, DX - MOVQ R15, AX - NOTQ AX - ADDQ DX, R10 - ANDQ R9, AX - XORQ CX, AX - ADDQ R10, AX - MOVQ R11, DI - MOVQ R13, BX - RORQ $0x1c, DI - MOVQ R11, DX - ANDQ R12, BX - RORQ $0x22, DX - MOVQ R11, CX - ANDQ R13, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R11, DX - MOVQ R12, CX - RORQ $0x27, DX - ANDQ R11, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R10 - ADDQ AX, R14 - ADDQ AX, R10 - MOVQ 608(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 504(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 568(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 496(BP), BX - ADDQ BX, AX - MOVQ AX, 624(BP) - MOVQ $0x5fcb6fab3ad6faec, DX - ADDQ AX, R9 - MOVQ R14, AX - ADDQ DX, R9 - MOVQ R14, CX - RORQ $0x0e, AX - MOVQ R14, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R14, CX - RORQ $0x29, DX - ANDQ R15, CX - XORQ AX, DX - MOVQ R14, AX - NOTQ AX - ADDQ DX, R9 - ANDQ R8, AX - XORQ CX, AX - ADDQ R9, AX - MOVQ R10, DI - MOVQ R12, BX - RORQ $0x1c, DI - MOVQ R10, DX - ANDQ R11, BX - RORQ $0x22, DX - MOVQ R10, CX - ANDQ R12, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R10, DX - MOVQ R11, CX - RORQ $0x27, DX - ANDQ R10, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R9 - ADDQ AX, R13 - ADDQ AX, R9 - MOVQ 616(BP), AX - MOVQ AX, CX - RORQ $0x13, AX - MOVQ CX, DX - RORQ $0x3d, CX - SHRQ $0x06, DX - MOVQ 512(BP), BX - XORQ CX, AX - MOVQ BX, CX - XORQ DX, AX - RORQ $0x01, BX - MOVQ CX, DX - SHRQ $0x07, DX - RORQ $0x08, CX - ADDQ 576(BP), AX - XORQ CX, BX - XORQ DX, BX - ADDQ 504(BP), BX - ADDQ BX, AX - MOVQ AX, 632(BP) - MOVQ $0x6c44198c4a475817, DX - ADDQ AX, R8 - MOVQ R13, AX - ADDQ DX, R8 - MOVQ R13, CX - RORQ $0x0e, AX - MOVQ R13, DX - RORQ $0x12, CX - XORQ CX, AX - MOVQ R13, CX - RORQ $0x29, DX - ANDQ R14, CX - XORQ AX, DX - MOVQ R13, AX - NOTQ AX - ADDQ DX, R8 - ANDQ R15, AX - XORQ CX, AX - ADDQ R8, AX - MOVQ R9, DI - MOVQ R11, BX - RORQ $0x1c, DI - MOVQ R9, DX - ANDQ R10, BX - RORQ $0x22, DX - MOVQ R9, CX - ANDQ R11, CX - XORQ DX, DI - XORQ CX, BX - MOVQ R9, DX - MOVQ R10, CX - RORQ $0x27, DX - ANDQ R9, CX - XORQ CX, BX - XORQ DX, DI - ADDQ DI, BX - MOVQ BX, R8 - ADDQ AX, R12 - ADDQ AX, R8 - MOVQ dig+0(FP), BP - ADDQ (BP), R8 - MOVQ R8, (BP) - ADDQ 8(BP), R9 - MOVQ R9, 8(BP) - ADDQ 16(BP), R10 - MOVQ R10, 16(BP) - ADDQ 24(BP), R11 - MOVQ R11, 24(BP) - ADDQ 32(BP), R12 - MOVQ R12, 32(BP) - ADDQ 40(BP), R13 - MOVQ R13, 40(BP) - ADDQ 48(BP), R14 - MOVQ R14, 48(BP) - ADDQ 56(BP), R15 - MOVQ R15, 56(BP) - ADDQ $0x80, SI - CMPQ SI, 640(SP) - JB loop - -end: - RET - -DATA PSHUFFLE_BYTE_FLIP_MASK<>+0(SB)/8, $0x0001020304050607 -DATA PSHUFFLE_BYTE_FLIP_MASK<>+8(SB)/8, $0x08090a0b0c0d0e0f -DATA PSHUFFLE_BYTE_FLIP_MASK<>+16(SB)/8, $0x1011121314151617 -DATA PSHUFFLE_BYTE_FLIP_MASK<>+24(SB)/8, $0x18191a1b1c1d1e1f -GLOBL PSHUFFLE_BYTE_FLIP_MASK<>(SB), RODATA|NOPTR, $32 - -// func blockAVX2(dig *digest, p []byte) -// Requires: AVX, AVX2, BMI2 -TEXT ·blockAVX2(SB), NOSPLIT, $56-32 - MOVQ dig+0(FP), SI - MOVQ p_base+8(FP), DI - MOVQ p_len+16(FP), DX - SHRQ $0x07, DX - SHLQ $0x07, DX - JZ done_hash - ADDQ DI, DX - MOVQ DX, 48(SP) - MOVQ (SI), AX - MOVQ 8(SI), BX - MOVQ 16(SI), CX - MOVQ 24(SI), R8 - MOVQ 32(SI), DX - MOVQ 40(SI), R9 - MOVQ 48(SI), R10 - MOVQ 56(SI), R11 - VMOVDQU PSHUFFLE_BYTE_FLIP_MASK<>+0(SB), Y9 - -loop0: - MOVQ ·_K+0(SB), BP - VMOVDQU (DI), Y4 - VPSHUFB Y9, Y4, Y4 - VMOVDQU 32(DI), Y5 - VPSHUFB Y9, Y5, Y5 - VMOVDQU 64(DI), Y6 - VPSHUFB Y9, Y6, Y6 - VMOVDQU 96(DI), Y7 - VPSHUFB Y9, Y7, Y7 - MOVQ DI, 40(SP) - MOVQ $0x00000004, 32(SP) - -loop1: - VPADDQ (BP), Y4, Y0 - VMOVDQU Y0, (SP) - VPERM2F128 $0x03, Y6, Y7, Y0 - VPALIGNR $0x08, Y6, Y0, Y0 - VPADDQ Y4, Y0, Y0 - VPERM2F128 $0x03, Y4, Y5, Y1 - VPALIGNR $0x08, Y4, Y1, Y1 - VPSRLQ $0x01, Y1, Y2 - VPSLLQ $0x3f, Y1, Y3 - VPOR Y2, Y3, Y3 - VPSRLQ $0x07, Y1, Y8 - MOVQ AX, DI - RORXQ $0x29, DX, R13 - RORXQ $0x12, DX, R14 - ADDQ (SP), R11 - ORQ CX, DI - MOVQ R9, R15 - RORXQ $0x22, AX, R12 - XORQ R14, R13 - XORQ R10, R15 - RORXQ $0x0e, DX, R14 - ANDQ DX, R15 - XORQ R14, R13 - RORXQ $0x27, AX, R14 - ADDQ R11, R8 - ANDQ BX, DI - XORQ R12, R14 - RORXQ $0x1c, AX, R12 - XORQ R10, R15 - XORQ R12, R14 - MOVQ AX, R12 - ANDQ CX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R11 - ADDQ R15, R8 - ADDQ R15, R11 - ADDQ DI, R11 - VPSRLQ $0x08, Y1, Y2 - VPSLLQ $0x38, Y1, Y1 - VPOR Y2, Y1, Y1 - VPXOR Y8, Y3, Y3 - VPXOR Y1, Y3, Y1 - VPADDQ Y1, Y0, Y0 - VPERM2F128 $0x00, Y0, Y0, Y4 - VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 - VPERM2F128 $0x11, Y7, Y7, Y2 - VPSRLQ $0x06, Y2, Y8 - MOVQ R11, DI - RORXQ $0x29, R8, R13 - RORXQ $0x12, R8, R14 - ADDQ 8(SP), R10 - ORQ BX, DI - MOVQ DX, R15 - RORXQ $0x22, R11, R12 - XORQ R14, R13 - XORQ R9, R15 - RORXQ $0x0e, R8, R14 - XORQ R14, R13 - RORXQ $0x27, R11, R14 - ANDQ R8, R15 - ADDQ R10, CX - ANDQ AX, DI - XORQ R12, R14 - RORXQ $0x1c, R11, R12 - XORQ R9, R15 - XORQ R12, R14 - MOVQ R11, R12 - ANDQ BX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R10 - ADDQ R15, CX - ADDQ R15, R10 - ADDQ DI, R10 - VPSRLQ $0x13, Y2, Y3 - VPSLLQ $0x2d, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y2, Y3 - VPSLLQ $0x03, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y4, Y4 - VPSRLQ $0x06, Y4, Y8 - MOVQ R10, DI - RORXQ $0x29, CX, R13 - ADDQ 16(SP), R9 - RORXQ $0x12, CX, R14 - ORQ AX, DI - MOVQ R8, R15 - XORQ DX, R15 - RORXQ $0x22, R10, R12 - XORQ R14, R13 - ANDQ CX, R15 - RORXQ $0x0e, CX, R14 - ADDQ R9, BX - ANDQ R11, DI - XORQ R14, R13 - RORXQ $0x27, R10, R14 - XORQ DX, R15 - XORQ R12, R14 - RORXQ $0x1c, R10, R12 - XORQ R12, R14 - MOVQ R10, R12 - ANDQ AX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R9 - ADDQ R15, BX - ADDQ R15, R9 - ADDQ DI, R9 - VPSRLQ $0x13, Y4, Y3 - VPSLLQ $0x2d, Y4, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y4, Y3 - VPSLLQ $0x03, Y4, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y0, Y2 - VPBLENDD $0xf0, Y2, Y4, Y4 - MOVQ R9, DI - RORXQ $0x29, BX, R13 - RORXQ $0x12, BX, R14 - ADDQ 24(SP), DX - ORQ R11, DI - MOVQ CX, R15 - RORXQ $0x22, R9, R12 - XORQ R14, R13 - XORQ R8, R15 - RORXQ $0x0e, BX, R14 - ANDQ BX, R15 - ADDQ DX, AX - ANDQ R10, DI - XORQ R14, R13 - XORQ R8, R15 - RORXQ $0x27, R9, R14 - ADDQ R13, R15 - XORQ R12, R14 - ADDQ R15, AX - RORXQ $0x1c, R9, R12 - XORQ R12, R14 - MOVQ R9, R12 - ANDQ R11, R12 - ORQ R12, DI - ADDQ R14, DX - ADDQ R15, DX - ADDQ DI, DX - VPADDQ 32(BP), Y5, Y0 - VMOVDQU Y0, (SP) - VPERM2F128 $0x03, Y7, Y4, Y0 - VPALIGNR $0x08, Y7, Y0, Y0 - VPADDQ Y5, Y0, Y0 - VPERM2F128 $0x03, Y5, Y6, Y1 - VPALIGNR $0x08, Y5, Y1, Y1 - VPSRLQ $0x01, Y1, Y2 - VPSLLQ $0x3f, Y1, Y3 - VPOR Y2, Y3, Y3 - VPSRLQ $0x07, Y1, Y8 - MOVQ DX, DI - RORXQ $0x29, AX, R13 - RORXQ $0x12, AX, R14 - ADDQ (SP), R8 - ORQ R10, DI - MOVQ BX, R15 - RORXQ $0x22, DX, R12 - XORQ R14, R13 - XORQ CX, R15 - RORXQ $0x0e, AX, R14 - ANDQ AX, R15 - XORQ R14, R13 - RORXQ $0x27, DX, R14 - ADDQ R8, R11 - ANDQ R9, DI - XORQ R12, R14 - RORXQ $0x1c, DX, R12 - XORQ CX, R15 - XORQ R12, R14 - MOVQ DX, R12 - ANDQ R10, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R8 - ADDQ R15, R11 - ADDQ R15, R8 - ADDQ DI, R8 - VPSRLQ $0x08, Y1, Y2 - VPSLLQ $0x38, Y1, Y1 - VPOR Y2, Y1, Y1 - VPXOR Y8, Y3, Y3 - VPXOR Y1, Y3, Y1 - VPADDQ Y1, Y0, Y0 - VPERM2F128 $0x00, Y0, Y0, Y5 - VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 - VPERM2F128 $0x11, Y4, Y4, Y2 - VPSRLQ $0x06, Y2, Y8 - MOVQ R8, DI - RORXQ $0x29, R11, R13 - RORXQ $0x12, R11, R14 - ADDQ 8(SP), CX - ORQ R9, DI - MOVQ AX, R15 - RORXQ $0x22, R8, R12 - XORQ R14, R13 - XORQ BX, R15 - RORXQ $0x0e, R11, R14 - XORQ R14, R13 - RORXQ $0x27, R8, R14 - ANDQ R11, R15 - ADDQ CX, R10 - ANDQ DX, DI - XORQ R12, R14 - RORXQ $0x1c, R8, R12 - XORQ BX, R15 - XORQ R12, R14 - MOVQ R8, R12 - ANDQ R9, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, CX - ADDQ R15, R10 - ADDQ R15, CX - ADDQ DI, CX - VPSRLQ $0x13, Y2, Y3 - VPSLLQ $0x2d, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y2, Y3 - VPSLLQ $0x03, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y5, Y5 - VPSRLQ $0x06, Y5, Y8 - MOVQ CX, DI - RORXQ $0x29, R10, R13 - ADDQ 16(SP), BX - RORXQ $0x12, R10, R14 - ORQ DX, DI - MOVQ R11, R15 - XORQ AX, R15 - RORXQ $0x22, CX, R12 - XORQ R14, R13 - ANDQ R10, R15 - RORXQ $0x0e, R10, R14 - ADDQ BX, R9 - ANDQ R8, DI - XORQ R14, R13 - RORXQ $0x27, CX, R14 - XORQ AX, R15 - XORQ R12, R14 - RORXQ $0x1c, CX, R12 - XORQ R12, R14 - MOVQ CX, R12 - ANDQ DX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, BX - ADDQ R15, R9 - ADDQ R15, BX - ADDQ DI, BX - VPSRLQ $0x13, Y5, Y3 - VPSLLQ $0x2d, Y5, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y5, Y3 - VPSLLQ $0x03, Y5, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y0, Y2 - VPBLENDD $0xf0, Y2, Y5, Y5 - MOVQ BX, DI - RORXQ $0x29, R9, R13 - RORXQ $0x12, R9, R14 - ADDQ 24(SP), AX - ORQ R8, DI - MOVQ R10, R15 - RORXQ $0x22, BX, R12 - XORQ R14, R13 - XORQ R11, R15 - RORXQ $0x0e, R9, R14 - ANDQ R9, R15 - ADDQ AX, DX - ANDQ CX, DI - XORQ R14, R13 - XORQ R11, R15 - RORXQ $0x27, BX, R14 - ADDQ R13, R15 - XORQ R12, R14 - ADDQ R15, DX - RORXQ $0x1c, BX, R12 - XORQ R12, R14 - MOVQ BX, R12 - ANDQ R8, R12 - ORQ R12, DI - ADDQ R14, AX - ADDQ R15, AX - ADDQ DI, AX - VPADDQ 64(BP), Y6, Y0 - VMOVDQU Y0, (SP) - VPERM2F128 $0x03, Y4, Y5, Y0 - VPALIGNR $0x08, Y4, Y0, Y0 - VPADDQ Y6, Y0, Y0 - VPERM2F128 $0x03, Y6, Y7, Y1 - VPALIGNR $0x08, Y6, Y1, Y1 - VPSRLQ $0x01, Y1, Y2 - VPSLLQ $0x3f, Y1, Y3 - VPOR Y2, Y3, Y3 - VPSRLQ $0x07, Y1, Y8 - MOVQ AX, DI - RORXQ $0x29, DX, R13 - RORXQ $0x12, DX, R14 - ADDQ (SP), R11 - ORQ CX, DI - MOVQ R9, R15 - RORXQ $0x22, AX, R12 - XORQ R14, R13 - XORQ R10, R15 - RORXQ $0x0e, DX, R14 - ANDQ DX, R15 - XORQ R14, R13 - RORXQ $0x27, AX, R14 - ADDQ R11, R8 - ANDQ BX, DI - XORQ R12, R14 - RORXQ $0x1c, AX, R12 - XORQ R10, R15 - XORQ R12, R14 - MOVQ AX, R12 - ANDQ CX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R11 - ADDQ R15, R8 - ADDQ R15, R11 - ADDQ DI, R11 - VPSRLQ $0x08, Y1, Y2 - VPSLLQ $0x38, Y1, Y1 - VPOR Y2, Y1, Y1 - VPXOR Y8, Y3, Y3 - VPXOR Y1, Y3, Y1 - VPADDQ Y1, Y0, Y0 - VPERM2F128 $0x00, Y0, Y0, Y6 - VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 - VPERM2F128 $0x11, Y5, Y5, Y2 - VPSRLQ $0x06, Y2, Y8 - MOVQ R11, DI - RORXQ $0x29, R8, R13 - RORXQ $0x12, R8, R14 - ADDQ 8(SP), R10 - ORQ BX, DI - MOVQ DX, R15 - RORXQ $0x22, R11, R12 - XORQ R14, R13 - XORQ R9, R15 - RORXQ $0x0e, R8, R14 - XORQ R14, R13 - RORXQ $0x27, R11, R14 - ANDQ R8, R15 - ADDQ R10, CX - ANDQ AX, DI - XORQ R12, R14 - RORXQ $0x1c, R11, R12 - XORQ R9, R15 - XORQ R12, R14 - MOVQ R11, R12 - ANDQ BX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R10 - ADDQ R15, CX - ADDQ R15, R10 - ADDQ DI, R10 - VPSRLQ $0x13, Y2, Y3 - VPSLLQ $0x2d, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y2, Y3 - VPSLLQ $0x03, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y6, Y6 - VPSRLQ $0x06, Y6, Y8 - MOVQ R10, DI - RORXQ $0x29, CX, R13 - ADDQ 16(SP), R9 - RORXQ $0x12, CX, R14 - ORQ AX, DI - MOVQ R8, R15 - XORQ DX, R15 - RORXQ $0x22, R10, R12 - XORQ R14, R13 - ANDQ CX, R15 - RORXQ $0x0e, CX, R14 - ADDQ R9, BX - ANDQ R11, DI - XORQ R14, R13 - RORXQ $0x27, R10, R14 - XORQ DX, R15 - XORQ R12, R14 - RORXQ $0x1c, R10, R12 - XORQ R12, R14 - MOVQ R10, R12 - ANDQ AX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R9 - ADDQ R15, BX - ADDQ R15, R9 - ADDQ DI, R9 - VPSRLQ $0x13, Y6, Y3 - VPSLLQ $0x2d, Y6, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y6, Y3 - VPSLLQ $0x03, Y6, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y0, Y2 - VPBLENDD $0xf0, Y2, Y6, Y6 - MOVQ R9, DI - RORXQ $0x29, BX, R13 - RORXQ $0x12, BX, R14 - ADDQ 24(SP), DX - ORQ R11, DI - MOVQ CX, R15 - RORXQ $0x22, R9, R12 - XORQ R14, R13 - XORQ R8, R15 - RORXQ $0x0e, BX, R14 - ANDQ BX, R15 - ADDQ DX, AX - ANDQ R10, DI - XORQ R14, R13 - XORQ R8, R15 - RORXQ $0x27, R9, R14 - ADDQ R13, R15 - XORQ R12, R14 - ADDQ R15, AX - RORXQ $0x1c, R9, R12 - XORQ R12, R14 - MOVQ R9, R12 - ANDQ R11, R12 - ORQ R12, DI - ADDQ R14, DX - ADDQ R15, DX - ADDQ DI, DX - VPADDQ 96(BP), Y7, Y0 - VMOVDQU Y0, (SP) - ADDQ $0x80, BP - VPERM2F128 $0x03, Y5, Y6, Y0 - VPALIGNR $0x08, Y5, Y0, Y0 - VPADDQ Y7, Y0, Y0 - VPERM2F128 $0x03, Y7, Y4, Y1 - VPALIGNR $0x08, Y7, Y1, Y1 - VPSRLQ $0x01, Y1, Y2 - VPSLLQ $0x3f, Y1, Y3 - VPOR Y2, Y3, Y3 - VPSRLQ $0x07, Y1, Y8 - MOVQ DX, DI - RORXQ $0x29, AX, R13 - RORXQ $0x12, AX, R14 - ADDQ (SP), R8 - ORQ R10, DI - MOVQ BX, R15 - RORXQ $0x22, DX, R12 - XORQ R14, R13 - XORQ CX, R15 - RORXQ $0x0e, AX, R14 - ANDQ AX, R15 - XORQ R14, R13 - RORXQ $0x27, DX, R14 - ADDQ R8, R11 - ANDQ R9, DI - XORQ R12, R14 - RORXQ $0x1c, DX, R12 - XORQ CX, R15 - XORQ R12, R14 - MOVQ DX, R12 - ANDQ R10, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, R8 - ADDQ R15, R11 - ADDQ R15, R8 - ADDQ DI, R8 - VPSRLQ $0x08, Y1, Y2 - VPSLLQ $0x38, Y1, Y1 - VPOR Y2, Y1, Y1 - VPXOR Y8, Y3, Y3 - VPXOR Y1, Y3, Y1 - VPADDQ Y1, Y0, Y0 - VPERM2F128 $0x00, Y0, Y0, Y7 - VPAND MASK_YMM_LO<>+0(SB), Y0, Y0 - VPERM2F128 $0x11, Y6, Y6, Y2 - VPSRLQ $0x06, Y2, Y8 - MOVQ R8, DI - RORXQ $0x29, R11, R13 - RORXQ $0x12, R11, R14 - ADDQ 8(SP), CX - ORQ R9, DI - MOVQ AX, R15 - RORXQ $0x22, R8, R12 - XORQ R14, R13 - XORQ BX, R15 - RORXQ $0x0e, R11, R14 - XORQ R14, R13 - RORXQ $0x27, R8, R14 - ANDQ R11, R15 - ADDQ CX, R10 - ANDQ DX, DI - XORQ R12, R14 - RORXQ $0x1c, R8, R12 - XORQ BX, R15 - XORQ R12, R14 - MOVQ R8, R12 - ANDQ R9, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, CX - ADDQ R15, R10 - ADDQ R15, CX - ADDQ DI, CX - VPSRLQ $0x13, Y2, Y3 - VPSLLQ $0x2d, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y2, Y3 - VPSLLQ $0x03, Y2, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y7, Y7 - VPSRLQ $0x06, Y7, Y8 - MOVQ CX, DI - RORXQ $0x29, R10, R13 - ADDQ 16(SP), BX - RORXQ $0x12, R10, R14 - ORQ DX, DI - MOVQ R11, R15 - XORQ AX, R15 - RORXQ $0x22, CX, R12 - XORQ R14, R13 - ANDQ R10, R15 - RORXQ $0x0e, R10, R14 - ADDQ BX, R9 - ANDQ R8, DI - XORQ R14, R13 - RORXQ $0x27, CX, R14 - XORQ AX, R15 - XORQ R12, R14 - RORXQ $0x1c, CX, R12 - XORQ R12, R14 - MOVQ CX, R12 - ANDQ DX, R12 - ADDQ R13, R15 - ORQ R12, DI - ADDQ R14, BX - ADDQ R15, R9 - ADDQ R15, BX - ADDQ DI, BX - VPSRLQ $0x13, Y7, Y3 - VPSLLQ $0x2d, Y7, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPSRLQ $0x3d, Y7, Y3 - VPSLLQ $0x03, Y7, Y1 - VPOR Y1, Y3, Y3 - VPXOR Y3, Y8, Y8 - VPADDQ Y8, Y0, Y2 - VPBLENDD $0xf0, Y2, Y7, Y7 - MOVQ BX, DI - RORXQ $0x29, R9, R13 - RORXQ $0x12, R9, R14 - ADDQ 24(SP), AX - ORQ R8, DI - MOVQ R10, R15 - RORXQ $0x22, BX, R12 - XORQ R14, R13 - XORQ R11, R15 - RORXQ $0x0e, R9, R14 - ANDQ R9, R15 - ADDQ AX, DX - ANDQ CX, DI - XORQ R14, R13 - XORQ R11, R15 - RORXQ $0x27, BX, R14 - ADDQ R13, R15 - XORQ R12, R14 - ADDQ R15, DX - RORXQ $0x1c, BX, R12 - XORQ R12, R14 - MOVQ BX, R12 - ANDQ R8, R12 - ORQ R12, DI - ADDQ R14, AX - ADDQ R15, AX - ADDQ DI, AX - SUBQ $0x01, 32(SP) - JNE loop1 - MOVQ $0x00000002, 32(SP) - -loop2: - VPADDQ (BP), Y4, Y0 - VMOVDQU Y0, (SP) - MOVQ R9, R15 - RORXQ $0x29, DX, R13 - RORXQ $0x12, DX, R14 - XORQ R10, R15 - XORQ R14, R13 - RORXQ $0x0e, DX, R14 - ANDQ DX, R15 - XORQ R14, R13 - RORXQ $0x22, AX, R12 - XORQ R10, R15 - RORXQ $0x27, AX, R14 - MOVQ AX, DI - XORQ R12, R14 - RORXQ $0x1c, AX, R12 - ADDQ (SP), R11 - ORQ CX, DI - XORQ R12, R14 - MOVQ AX, R12 - ANDQ BX, DI - ANDQ CX, R12 - ADDQ R13, R15 - ADDQ R11, R8 - ORQ R12, DI - ADDQ R14, R11 - ADDQ R15, R8 - ADDQ R15, R11 - MOVQ DX, R15 - RORXQ $0x29, R8, R13 - RORXQ $0x12, R8, R14 - XORQ R9, R15 - XORQ R14, R13 - RORXQ $0x0e, R8, R14 - ANDQ R8, R15 - ADDQ DI, R11 - XORQ R14, R13 - RORXQ $0x22, R11, R12 - XORQ R9, R15 - RORXQ $0x27, R11, R14 - MOVQ R11, DI - XORQ R12, R14 - RORXQ $0x1c, R11, R12 - ADDQ 8(SP), R10 - ORQ BX, DI - XORQ R12, R14 - MOVQ R11, R12 - ANDQ AX, DI - ANDQ BX, R12 - ADDQ R13, R15 - ADDQ R10, CX - ORQ R12, DI - ADDQ R14, R10 - ADDQ R15, CX - ADDQ R15, R10 - MOVQ R8, R15 - RORXQ $0x29, CX, R13 - RORXQ $0x12, CX, R14 - XORQ DX, R15 - XORQ R14, R13 - RORXQ $0x0e, CX, R14 - ANDQ CX, R15 - ADDQ DI, R10 - XORQ R14, R13 - RORXQ $0x22, R10, R12 - XORQ DX, R15 - RORXQ $0x27, R10, R14 - MOVQ R10, DI - XORQ R12, R14 - RORXQ $0x1c, R10, R12 - ADDQ 16(SP), R9 - ORQ AX, DI - XORQ R12, R14 - MOVQ R10, R12 - ANDQ R11, DI - ANDQ AX, R12 - ADDQ R13, R15 - ADDQ R9, BX - ORQ R12, DI - ADDQ R14, R9 - ADDQ R15, BX - ADDQ R15, R9 - MOVQ CX, R15 - RORXQ $0x29, BX, R13 - RORXQ $0x12, BX, R14 - XORQ R8, R15 - XORQ R14, R13 - RORXQ $0x0e, BX, R14 - ANDQ BX, R15 - ADDQ DI, R9 - XORQ R14, R13 - RORXQ $0x22, R9, R12 - XORQ R8, R15 - RORXQ $0x27, R9, R14 - MOVQ R9, DI - XORQ R12, R14 - RORXQ $0x1c, R9, R12 - ADDQ 24(SP), DX - ORQ R11, DI - XORQ R12, R14 - MOVQ R9, R12 - ANDQ R10, DI - ANDQ R11, R12 - ADDQ R13, R15 - ADDQ DX, AX - ORQ R12, DI - ADDQ R14, DX - ADDQ R15, AX - ADDQ R15, DX - ADDQ DI, DX - VPADDQ 32(BP), Y5, Y0 - VMOVDQU Y0, (SP) - ADDQ $0x40, BP - MOVQ BX, R15 - RORXQ $0x29, AX, R13 - RORXQ $0x12, AX, R14 - XORQ CX, R15 - XORQ R14, R13 - RORXQ $0x0e, AX, R14 - ANDQ AX, R15 - XORQ R14, R13 - RORXQ $0x22, DX, R12 - XORQ CX, R15 - RORXQ $0x27, DX, R14 - MOVQ DX, DI - XORQ R12, R14 - RORXQ $0x1c, DX, R12 - ADDQ (SP), R8 - ORQ R10, DI - XORQ R12, R14 - MOVQ DX, R12 - ANDQ R9, DI - ANDQ R10, R12 - ADDQ R13, R15 - ADDQ R8, R11 - ORQ R12, DI - ADDQ R14, R8 - ADDQ R15, R11 - ADDQ R15, R8 - MOVQ AX, R15 - RORXQ $0x29, R11, R13 - RORXQ $0x12, R11, R14 - XORQ BX, R15 - XORQ R14, R13 - RORXQ $0x0e, R11, R14 - ANDQ R11, R15 - ADDQ DI, R8 - XORQ R14, R13 - RORXQ $0x22, R8, R12 - XORQ BX, R15 - RORXQ $0x27, R8, R14 - MOVQ R8, DI - XORQ R12, R14 - RORXQ $0x1c, R8, R12 - ADDQ 8(SP), CX - ORQ R9, DI - XORQ R12, R14 - MOVQ R8, R12 - ANDQ DX, DI - ANDQ R9, R12 - ADDQ R13, R15 - ADDQ CX, R10 - ORQ R12, DI - ADDQ R14, CX - ADDQ R15, R10 - ADDQ R15, CX - MOVQ R11, R15 - RORXQ $0x29, R10, R13 - RORXQ $0x12, R10, R14 - XORQ AX, R15 - XORQ R14, R13 - RORXQ $0x0e, R10, R14 - ANDQ R10, R15 - ADDQ DI, CX - XORQ R14, R13 - RORXQ $0x22, CX, R12 - XORQ AX, R15 - RORXQ $0x27, CX, R14 - MOVQ CX, DI - XORQ R12, R14 - RORXQ $0x1c, CX, R12 - ADDQ 16(SP), BX - ORQ DX, DI - XORQ R12, R14 - MOVQ CX, R12 - ANDQ R8, DI - ANDQ DX, R12 - ADDQ R13, R15 - ADDQ BX, R9 - ORQ R12, DI - ADDQ R14, BX - ADDQ R15, R9 - ADDQ R15, BX - MOVQ R10, R15 - RORXQ $0x29, R9, R13 - RORXQ $0x12, R9, R14 - XORQ R11, R15 - XORQ R14, R13 - RORXQ $0x0e, R9, R14 - ANDQ R9, R15 - ADDQ DI, BX - XORQ R14, R13 - RORXQ $0x22, BX, R12 - XORQ R11, R15 - RORXQ $0x27, BX, R14 - MOVQ BX, DI - XORQ R12, R14 - RORXQ $0x1c, BX, R12 - ADDQ 24(SP), AX - ORQ R8, DI - XORQ R12, R14 - MOVQ BX, R12 - ANDQ CX, DI - ANDQ R8, R12 - ADDQ R13, R15 - ADDQ AX, DX - ORQ R12, DI - ADDQ R14, AX - ADDQ R15, DX - ADDQ R15, AX - ADDQ DI, AX - VMOVDQU Y6, Y4 - VMOVDQU Y7, Y5 - SUBQ $0x01, 32(SP) - JNE loop2 - ADDQ (SI), AX - MOVQ AX, (SI) - ADDQ 8(SI), BX - MOVQ BX, 8(SI) - ADDQ 16(SI), CX - MOVQ CX, 16(SI) - ADDQ 24(SI), R8 - MOVQ R8, 24(SI) - ADDQ 32(SI), DX - MOVQ DX, 32(SI) - ADDQ 40(SI), R9 - MOVQ R9, 40(SI) - ADDQ 48(SI), R10 - MOVQ R10, 48(SI) - ADDQ 56(SI), R11 - MOVQ R11, 56(SI) - MOVQ 40(SP), DI - ADDQ $0x80, DI - CMPQ DI, 48(SP) - JNE loop0 - -done_hash: - VZEROUPPER - RET - -DATA MASK_YMM_LO<>+0(SB)/8, $0x0000000000000000 -DATA MASK_YMM_LO<>+8(SB)/8, $0x0000000000000000 -DATA MASK_YMM_LO<>+16(SB)/8, $0xffffffffffffffff -DATA MASK_YMM_LO<>+24(SB)/8, $0xffffffffffffffff -GLOBL MASK_YMM_LO<>(SB), RODATA|NOPTR, $32 diff --git a/crypto/sha512/sha512block_arm64.go b/crypto/sha512/sha512block_arm64.go deleted file mode 100644 index eea57e73f40..00000000000 --- a/crypto/sha512/sha512block_arm64.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha512 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -func block(dig *digest, p []byte) { - if cpu.ARM64.HasSHA512 { - blockAsm(dig, p) - return - } - blockGeneric(dig, p) -} - -//go:noescape -func blockAsm(dig *digest, p []byte) diff --git a/crypto/sha512/sha512block_s390x.go b/crypto/sha512/sha512block_s390x.go deleted file mode 100644 index be2de5e1ec5..00000000000 --- a/crypto/sha512/sha512block_s390x.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package sha512 - -import "github.com/runZeroInc/excrypto/internal/cpu" - -var useAsm = cpu.S390X.HasSHA512 diff --git a/crypto/ssl3/tls/cipher_suites.go b/crypto/ssl3/tls/cipher_suites.go index 1f273864778..28263d42713 100644 --- a/crypto/ssl3/tls/cipher_suites.go +++ b/crypto/ssl3/tls/cipher_suites.go @@ -5,7 +5,7 @@ package tls import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/des" diff --git a/crypto/ssl3/tls/handshake_client.go b/crypto/ssl3/tls/handshake_client.go index ea492fc8323..8ec080f94eb 100644 --- a/crypto/ssl3/tls/handshake_client.go +++ b/crypto/ssl3/tls/handshake_client.go @@ -6,7 +6,6 @@ package tls import ( "bytes" - "encoding/asn1" "encoding/binary" "errors" "fmt" @@ -16,6 +15,8 @@ import ( "strconv" "time" + "github.com/runZeroInc/excrypto/encoding/asn1" + "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/rsa" diff --git a/crypto/ssl3/tls/prf.go b/crypto/ssl3/tls/prf.go index b668419a231..0eddd000b39 100644 --- a/crypto/ssl3/tls/prf.go +++ b/crypto/ssl3/tls/prf.go @@ -6,7 +6,8 @@ package tls import ( "errors" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/hmac" diff --git a/crypto/ssl3/zcrypto_schemas/__init__.py b/crypto/ssl3/zcrypto_schemas/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crypto/subtle/constant_time.go b/crypto/subtle/constant_time.go index 4e0527f9d5a..8885e8048bf 100644 --- a/crypto/subtle/constant_time.go +++ b/crypto/subtle/constant_time.go @@ -6,57 +6,41 @@ // code but require careful thought to use correctly. package subtle +import "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + // ConstantTimeCompare returns 1 if the two slices, x and y, have equal contents // and 0 otherwise. The time taken is a function of the length of the slices and // is independent of the contents. If the lengths of x and y do not match it // returns 0 immediately. func ConstantTimeCompare(x, y []byte) int { - if len(x) != len(y) { - return 0 - } - - var v byte - - for i := 0; i < len(x); i++ { - v |= x[i] ^ y[i] - } - - return ConstantTimeByteEq(v, 0) + return subtle.ConstantTimeCompare(x, y) } // ConstantTimeSelect returns x if v == 1 and y if v == 0. // Its behavior is undefined if v takes any other value. -func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y } +func ConstantTimeSelect(v, x, y int) int { + return subtle.ConstantTimeSelect(v, x, y) +} // ConstantTimeByteEq returns 1 if x == y and 0 otherwise. func ConstantTimeByteEq(x, y uint8) int { - return int((uint32(x^y) - 1) >> 31) + return subtle.ConstantTimeByteEq(x, y) } // ConstantTimeEq returns 1 if x == y and 0 otherwise. func ConstantTimeEq(x, y int32) int { - return int((uint64(uint32(x^y)) - 1) >> 63) + return subtle.ConstantTimeEq(x, y) } // ConstantTimeCopy copies the contents of y into x (a slice of equal length) // if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v // takes any other value. func ConstantTimeCopy(v int, x, y []byte) { - if len(x) != len(y) { - panic("subtle: slices have different lengths") - } - - xmask := byte(v - 1) - ymask := byte(^(v - 1)) - for i := 0; i < len(x); i++ { - x[i] = x[i]&xmask | y[i]&ymask - } + subtle.ConstantTimeCopy(v, x, y) } // ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. // Its behavior is undefined if x or y are negative or > 2**31 - 1. func ConstantTimeLessOrEq(x, y int) int { - x32 := int32(x) - y32 := int32(y) - return int(((x32 - y32 - 1) >> 31) & 1) + return subtle.ConstantTimeLessOrEq(x, y) } diff --git a/crypto/subtle/dit.go b/crypto/subtle/dit.go new file mode 100644 index 00000000000..086c83e3596 --- /dev/null +++ b/crypto/subtle/dit.go @@ -0,0 +1,47 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +/* excrypto +// WithDataIndependentTiming enables architecture specific features which ensure +// that the timing of specific instructions is independent of their inputs +// before executing f. On f returning it disables these features. +// +// WithDataIndependentTiming should only be used when f is written to make use +// of constant-time operations. WithDataIndependentTiming does not make +// variable-time code constant-time. +// +// WithDataIndependentTiming may lock the current goroutine to the OS thread for +// the duration of f. Calls to WithDataIndependentTiming may be nested. +// +// On Arm64 processors with FEAT_DIT, WithDataIndependentTiming enables +// PSTATE.DIT. See https://developer.arm.com/documentation/ka005181/1-0/?lang=en. +// +// Currently, on all other architectures WithDataIndependentTiming executes f immediately +// with no other side-effects. +// +//go:noinline +func WithDataIndependentTiming(f func()) { + if !sys.DITSupported { + f() + return + } + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + alreadyEnabled := sys.EnableDIT() + + // disableDIT is called in a deferred function so that if f panics we will + // still disable DIT, in case the panic is recovered further up the stack. + defer func() { + if !alreadyEnabled { + sys.DisableDIT() + } + }() + + f() +} +*/ diff --git a/crypto/subtle/dit_test.go b/crypto/subtle/dit_test.go new file mode 100644 index 00000000000..3a3ee6d1bdf --- /dev/null +++ b/crypto/subtle/dit_test.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +/* excrypto +func TestWithDataIndependentTiming(t *testing.T) { + if !cpu.ARM64.HasDIT { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + WithDataIndependentTiming(func() { + if !sys.DITEnabled() { + t.Fatal("dit not enabled within WithDataIndependentTiming closure") + } + + WithDataIndependentTiming(func() { + if !sys.DITEnabled() { + t.Fatal("dit not enabled within nested WithDataIndependentTiming closure") + } + }) + + if !sys.DITEnabled() { + t.Fatal("dit not enabled after return from nested WithDataIndependentTiming closure") + } + }) + + if !ditAlreadyEnabled && sys.DITEnabled() { + t.Fatal("dit not unset after returning from WithDataIndependentTiming closure") + } +} + +func TestDITPanic(t *testing.T) { + if !cpu.ARM64.HasDIT { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + defer func() { + e := recover() + if e == nil { + t.Fatal("didn't panic") + } + if !ditAlreadyEnabled && sys.DITEnabled() { + t.Error("DIT still enabled after panic inside of WithDataIndependentTiming closure") + } + }() + + WithDataIndependentTiming(func() { + if !sys.DITEnabled() { + t.Fatal("dit not enabled within WithDataIndependentTiming closure") + } + + panic("bad") + }) +} +*/ diff --git a/crypto/subtle/xor.go b/crypto/subtle/xor.go index 158dbcede90..f8979e863a4 100644 --- a/crypto/subtle/xor.go +++ b/crypto/subtle/xor.go @@ -4,18 +4,16 @@ package subtle +import "github.com/runZeroInc/excrypto/crypto/internal/fips140/subtle" + // XORBytes sets dst[i] = x[i] ^ y[i] for all i < n = min(len(x), len(y)), // returning n, the number of bytes written to dst. +// // If dst does not have length at least n, // XORBytes panics without writing anything to dst. +// +// dst and x or y may overlap exactly or not at all, +// otherwise XORBytes may panic. func XORBytes(dst, x, y []byte) int { - n := min(len(x), len(y)) - if n == 0 { - return 0 - } - if n > len(dst) { - panic("subtle.XORBytes: dst too short") - } - xorBytes(&dst[0], &x[0], &y[0], n) // arch-specific - return n + return subtle.XORBytes(dst, x, y) } diff --git a/crypto/subtle/xor_amd64.go b/crypto/subtle/xor_amd64.go deleted file mode 100644 index 3bb2f08b7c9..00000000000 --- a/crypto/subtle/xor_amd64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package subtle - -//go:noescape -func xorBytes(dst, a, b *byte, n int) diff --git a/crypto/subtle/xor_arm64.go b/crypto/subtle/xor_arm64.go deleted file mode 100644 index 65bab4c6574..00000000000 --- a/crypto/subtle/xor_arm64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -package subtle - -//go:noescape -func xorBytes(dst, a, b *byte, n int) diff --git a/crypto/subtle/xor_linux_test.go b/crypto/subtle/xor_linux_test.go new file mode 100644 index 00000000000..eee6e468712 --- /dev/null +++ b/crypto/subtle/xor_linux_test.go @@ -0,0 +1,47 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle_test + +import ( + "syscall" + "testing" + + "github.com/runZeroInc/excrypto/crypto/subtle" +) + +// dangerousSlice returns a slice which is immediately +// preceded and followed by a faulting page. +// Copied from the bytes package tests. +func dangerousSlice(t *testing.T) []byte { + pagesize := syscall.Getpagesize() + b, err := syscall.Mmap(0, 0, 3*pagesize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANONYMOUS|syscall.MAP_PRIVATE) + if err != nil { + t.Fatalf("mmap failed %s", err) + } + err = syscall.Mprotect(b[:pagesize], syscall.PROT_NONE) + if err != nil { + t.Fatalf("mprotect low failed %s\n", err) + } + err = syscall.Mprotect(b[2*pagesize:], syscall.PROT_NONE) + if err != nil { + t.Fatalf("mprotect high failed %s\n", err) + } + return b[pagesize : 2*pagesize] +} + +func TestXORBytesBoundary(t *testing.T) { + safe := make([]byte, syscall.Getpagesize()*2) + spicy := dangerousSlice(t) + for i := 1; i <= syscall.Getpagesize(); i++ { + start := spicy[:i] + end := spicy[len(spicy)-i:] + subtle.XORBytes(end, safe, safe[:i]) + subtle.XORBytes(start, safe, safe[:i]) + subtle.XORBytes(safe, start, safe) + subtle.XORBytes(safe, end, safe) + subtle.XORBytes(safe, safe, start) + subtle.XORBytes(safe, safe, end) + } +} diff --git a/crypto/subtle/xor_loong64.s b/crypto/subtle/xor_loong64.s deleted file mode 100644 index 09dc80eb939..00000000000 --- a/crypto/subtle/xor_loong64.s +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !purego - -#include "textflag.h" - -// func xorBytes(dst, a, b *byte, n int) -TEXT ·xorBytes(SB), NOSPLIT, $0 - MOVV dst+0(FP), R4 - MOVV a+8(FP), R5 - MOVV b+16(FP), R6 - MOVV n+24(FP), R7 - - MOVV $64, R9 - BGEU R7, R9, loop64 // n >= 64 -tail: - SRLV $1, R9 - BGEU R7, R9, xor_32 // n >= 32 && n < 64 - SRLV $1, R9 - BGEU R7, R9, xor_16 // n >= 16 && n < 32 - SRLV $1, R9 - BGEU R7, R9, xor_8 // n >= 8 && n < 16 - SRLV $1, R9 - BGEU R7, R9, xor_4 // n >= 4 && n < 8 - SRLV $1, R9 - BGEU R7, R9, xor_2 // n >= 2 && n < 4 - SRLV $1, R9 - BGEU R7, R9, xor_1 // n = 1 - -loop64: - MOVV (R5), R10 - MOVV 8(R5), R11 - MOVV 16(R5), R12 - MOVV 24(R5), R13 - MOVV (R6), R14 - MOVV 8(R6), R15 - MOVV 16(R6), R16 - MOVV 24(R6), R17 - XOR R10, R14 - XOR R11, R15 - XOR R12, R16 - XOR R13, R17 - MOVV R14, (R4) - MOVV R15, 8(R4) - MOVV R16, 16(R4) - MOVV R17, 24(R4) - MOVV 32(R5), R10 - MOVV 40(R5), R11 - MOVV 48(R5), R12 - MOVV 56(R5), R13 - MOVV 32(R6), R14 - MOVV 40(R6), R15 - MOVV 48(R6), R16 - MOVV 56(R6), R17 - XOR R10, R14 - XOR R11, R15 - XOR R12, R16 - XOR R13, R17 - MOVV R14, 32(R4) - MOVV R15, 40(R4) - MOVV R16, 48(R4) - MOVV R17, 56(R4) - ADDV $64, R5 - ADDV $64, R6 - ADDV $64, R4 - SUBV $64, R7 - // 64 in R9 - BGEU R7, R9, loop64 - BEQ R7, R0, end - -xor_32_check: - SRLV $1, R9 - BLT R7, R9, xor_16_check -xor_32: - MOVV (R5), R10 - MOVV 8(R5), R11 - MOVV 16(R5), R12 - MOVV 24(R5), R13 - MOVV (R6), R14 - MOVV 8(R6), R15 - MOVV 16(R6), R16 - MOVV 24(R6), R17 - XOR R10, R14 - XOR R11, R15 - XOR R12, R16 - XOR R13, R17 - MOVV R14, (R4) - MOVV R15, 8(R4) - MOVV R16, 16(R4) - MOVV R17, 24(R4) - ADDV $32, R5 - ADDV $32, R6 - ADDV $32, R4 - SUBV $32, R7 - BEQ R7, R0, end - -xor_16_check: - SRLV $1, R9 - BLT R7, R9, xor_8_check -xor_16: - MOVV (R5), R10 - MOVV 8(R5), R11 - MOVV (R6), R12 - MOVV 8(R6), R13 - XOR R10, R12 - XOR R11, R13 - MOVV R12, (R4) - MOVV R13, 8(R4) - ADDV $16, R5 - ADDV $16, R6 - ADDV $16, R4 - SUBV $16, R7 - BEQ R7, R0, end - -xor_8_check: - SRLV $1, R9 - BLT R7, R9, xor_4_check -xor_8: - MOVV (R5), R10 - MOVV (R6), R11 - XOR R10, R11 - MOVV R11, (R4) - ADDV $8, R5 - ADDV $8, R6 - ADDV $8, R4 - SUBV $8, R7 - BEQ R7, R0, end - -xor_4_check: - SRLV $1, R9 - BLT R7, R9, xor_2_check -xor_4: - MOVW (R5), R10 - MOVW (R6), R11 - XOR R10, R11 - MOVW R11, (R4) - ADDV $4, R5 - ADDV $4, R6 - ADDV $4, R4 - SUBV $4, R7 - BEQ R7, R0, end - -xor_2_check: - SRLV $1, R9 - BLT R7, R9, xor_1 -xor_2: - MOVH (R5), R10 - MOVH (R6), R11 - XOR R10, R11 - MOVH R11, (R4) - ADDV $2, R5 - ADDV $2, R6 - ADDV $2, R4 - SUBV $2, R7 - BEQ R7, R0, end - -xor_1: - MOVB (R5), R10 - MOVB (R6), R11 - XOR R10, R11 - MOVB R11, (R4) - -end: - RET diff --git a/crypto/subtle/xor_test.go b/crypto/subtle/xor_test.go index 65dbe7c953f..7d780b9aab4 100644 --- a/crypto/subtle/xor_test.go +++ b/crypto/subtle/xor_test.go @@ -6,13 +6,11 @@ package subtle_test import ( "bytes" + . "crypto/subtle" "fmt" - "io" "testing" "crypto/rand" - - . "github.com/runZeroInc/excrypto/crypto/subtle" ) func TestXORBytes(t *testing.T) { @@ -23,32 +21,50 @@ func TestXORBytes(t *testing.T) { for alignP := 0; alignP < 8; alignP++ { for alignQ := 0; alignQ < 8; alignQ++ { for alignD := 0; alignD < 8; alignD++ { - p := make([]byte, alignP+n, alignP+n+10)[alignP:] - q := make([]byte, alignQ+n, alignQ+n+10)[alignQ:] + p := make([]byte, alignP+n, alignP+n+100)[alignP:] + q := make([]byte, alignQ+n, alignQ+n+100)[alignQ:] if n&1 != 0 { p = p[:n] } else { q = q[:n] } - if _, err := io.ReadFull(rand.Reader, p); err != nil { - t.Fatal(err) - } - if _, err := io.ReadFull(rand.Reader, q); err != nil { - t.Fatal(err) + rand.Read(p) + rand.Read(q) + + d := make([]byte, alignD+n+100) + rand.Read(d) + + want := bytes.Clone(d) + for i := range n { + want[alignD+i] = p[i] ^ q[i] } - d := make([]byte, alignD+n, alignD+n+10) - for i := range d { - d[i] = 0xdd + if nn := XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want) + } else if nn != n { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n) } - want := make([]byte, len(d), cap(d)) - copy(want[:cap(want)], d[:cap(d)]) - for i := 0; i < n; i++ { - want[alignD+i] = p[i] ^ q[i] + p1 := bytes.Clone(p) + if nn := XORBytes(p, p, q); !bytes.Equal(p, want[alignD:alignD+n]) { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want) + } else if nn != n { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n) + } + if nn := XORBytes(q, p1, q); !bytes.Equal(q, want[alignD:alignD+n]) { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want) + } else if nn != n { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n) } - if XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) { - t.Fatalf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want) + if nn := XORBytes(p, p, p); !bytes.Equal(p, make([]byte, n)) { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %x, want %x", n, alignP, alignQ, alignD, p, make([]byte, n)) + } else if nn != n { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n) + } + if nn := XORBytes(p1, q, q); !bytes.Equal(p1, make([]byte, n)) { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %x, want %x", n, alignP, alignQ, alignD, p1, make([]byte, n)) + } else if nn != n { + t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n) } } } @@ -63,13 +79,21 @@ func TestXorBytesPanic(t *testing.T) { mustPanic(t, "subtle.XORBytes: dst too short", func() { XORBytes(make([]byte, 1), make([]byte, 2), make([]byte, 3)) }) + mustPanic(t, "subtle.XORBytes: invalid overlap", func() { + x := make([]byte, 3) + XORBytes(x, x[1:], make([]byte, 2)) + }) + mustPanic(t, "subtle.XORBytes: invalid overlap", func() { + x := make([]byte, 3) + XORBytes(x, make([]byte, 2), x[1:]) + }) } func BenchmarkXORBytes(b *testing.B) { dst := make([]byte, 1<<15) data0 := make([]byte, 1<<15) data1 := make([]byte, 1<<15) - sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15} + sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 13, 1 << 15} for _, size := range sizes { b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) { s0 := data0[:size] @@ -82,9 +106,30 @@ func BenchmarkXORBytes(b *testing.B) { } } +func BenchmarkXORBytesAlignment(b *testing.B) { + dst := make([]byte, 8+1<<11) + data0 := make([]byte, 8+1<<11) + data1 := make([]byte, 8+1<<11) + sizes := []int64{1 << 3, 1 << 7, 1 << 11} + for _, size := range sizes { + for offset := int64(0); offset < 8; offset++ { + b.Run(fmt.Sprintf("%dBytes%dOffset", size, offset), func(b *testing.B) { + d := dst[offset : offset+size] + s0 := data0[offset : offset+size] + s1 := data1[offset : offset+size] + b.SetBytes(int64(size)) + for i := 0; i < b.N; i++ { + XORBytes(d, s0, s1) + } + }) + } + } +} + func mustPanic(t *testing.T, expected string, f func()) { t.Helper() defer func() { + t.Helper() switch msg := recover().(type) { case nil: t.Errorf("expected panic(%q), but did not panic", expected) diff --git a/crypto/tls/auth.go b/crypto/tls/auth.go index f4778e9f3a4..54e4d1ce793 100644 --- a/crypto/tls/auth.go +++ b/crypto/tls/auth.go @@ -8,10 +8,13 @@ import ( "bytes" "errors" "fmt" - "hash" "io" + "slices" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/ed25519" "github.com/runZeroInc/excrypto/crypto/elliptic" @@ -149,104 +152,94 @@ func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash c var rsaSignatureSchemes = []struct { scheme SignatureScheme minModulusBytes int - maxVersion uint16 }{ // RSA-PSS is used with PSSSaltLengthEqualsHash, and requires // emLen >= hLen + sLen + 2 - {PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13}, - {PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13}, - {PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13}, + {PSSWithSHA256, crypto.SHA256.Size()*2 + 2}, + {PSSWithSHA384, crypto.SHA384.Size()*2 + 2}, + {PSSWithSHA512, crypto.SHA512.Size()*2 + 2}, // PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires // emLen >= len(prefix) + hLen + 11 - // TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS. - {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12}, - {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12}, - {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12}, - {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12}, + {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11}, + {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11}, + {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11}, + {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11}, } -// signatureSchemesForCertificate returns the list of supported SignatureSchemes -// for a given certificate, based on the public key and the protocol version, -// and optionally filtered by its explicit SupportedSignatureAlgorithms. -// -// This function must be kept in sync with supportedSignatureAlgorithms. -// FIPS filtering is applied in the caller, selectSignatureScheme. -func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { - priv, ok := cert.PrivateKey.(crypto.Signer) - if !ok { - return nil - } - - var sigAlgs []SignatureScheme - switch pub := priv.Public().(type) { +func signatureSchemesForPublicKey(version uint16, pub crypto.PublicKey) []SignatureScheme { + switch pub := pub.(type) { case *ecdsa.PublicKey: - if version != VersionTLS13 { + if version < VersionTLS13 { // In TLS 1.2 and earlier, ECDSA algorithms are not // constrained to a single curve. - sigAlgs = []SignatureScheme{ + return []SignatureScheme{ ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, ECDSAWithSHA1, } - break } - switch pub.Curve { case elliptic.P256(): - sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256} + return []SignatureScheme{ECDSAWithP256AndSHA256} case elliptic.P384(): - sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384} + return []SignatureScheme{ECDSAWithP384AndSHA384} case elliptic.P521(): - sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512} + return []SignatureScheme{ECDSAWithP521AndSHA512} default: return nil } case *rsa.PublicKey: size := pub.Size() - sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes)) + sigAlgs := make([]SignatureScheme, 0, len(rsaSignatureSchemes)) for _, candidate := range rsaSignatureSchemes { - if size >= candidate.minModulusBytes && version <= candidate.maxVersion { + if size >= candidate.minModulusBytes { sigAlgs = append(sigAlgs, candidate.scheme) } } + return sigAlgs case ed25519.PublicKey: - sigAlgs = []SignatureScheme{Ed25519} + return []SignatureScheme{Ed25519} default: return nil } - - if cert.SupportedSignatureAlgorithms != nil { - var filteredSigAlgs []SignatureScheme - for _, sigAlg := range sigAlgs { - if isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) { - filteredSigAlgs = append(filteredSigAlgs, sigAlg) - } - } - return filteredSigAlgs - } - return sigAlgs } // selectSignatureScheme picks a SignatureScheme from the peer's preference list // that works with the selected certificate. It's only called for protocol // versions that support signature algorithms, so TLS 1.2 and 1.3. func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) { - supportedAlgs := signatureSchemesForCertificate(vers, c) + priv, ok := c.PrivateKey.(crypto.Signer) + if !ok { + return 0, unsupportedCertificateError(c) + } + supportedAlgs := signatureSchemesForPublicKey(vers, priv.Public()) + if c.SupportedSignatureAlgorithms != nil { + supportedAlgs = slices.DeleteFunc(supportedAlgs, func(sigAlg SignatureScheme) bool { + return !isSupportedSignatureAlgorithm(sigAlg, c.SupportedSignatureAlgorithms) + }) + } + // Filter out any unsupported signature algorithms, for example due to + // FIPS 140-3 policy, tlssha1=0, or protocol version. + supportedAlgs = slices.DeleteFunc(supportedAlgs, func(sigAlg SignatureScheme) bool { + return isDisabledSignatureAlgorithm(vers, sigAlg, false) + }) if len(supportedAlgs) == 0 { return 0, unsupportedCertificateError(c) } if len(peerAlgs) == 0 && vers == VersionTLS12 { // For TLS 1.2, if the client didn't send signature_algorithms then we // can assume that it supports SHA1. See RFC 5246, Section 7.4.1.4.1. + // RFC 9155 made signature_algorithms mandatory in TLS 1.2, and we gated + // it behind the tlssha1 GODEBUG setting. + if tlssha1.Value() != "1" { + return 0, errors.New("tls: missing signature_algorithms from TLS 1.2 peer") + } peerAlgs = []SignatureScheme{PKCS1WithSHA1, ECDSAWithSHA1} } // Pick signature scheme in the peer's preference order, as our // preference order is not configurable. for _, preferredAlg := range peerAlgs { - if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, defaultSupportedSignatureAlgorithmsFIPS) { - continue - } if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { return preferredAlg, nil } diff --git a/crypto/tls/auth_test.go b/crypto/tls/auth_test.go index fb07971aa4b..603f8ba212e 100644 --- a/crypto/tls/auth_test.go +++ b/crypto/tls/auth_test.go @@ -5,8 +5,12 @@ package tls import ( - "github.com/runZeroInc/excrypto/crypto" + "os" "testing" + + "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" ) func TestSignatureSelection(t *testing.T) { @@ -32,31 +36,42 @@ func TestSignatureSelection(t *testing.T) { cert *Certificate peerSigAlgs []SignatureScheme tlsVersion uint16 + godebug string expectedSigAlg SignatureScheme expectedSigType uint8 expectedHash crypto.Hash }{ - {rsaCert, []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, - {rsaCert, []SignatureScheme{PKCS1WithSHA512, PKCS1WithSHA1}, VersionTLS12, PKCS1WithSHA512, signaturePKCS1v15, crypto.SHA512}, - {rsaCert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PSSWithSHA256, signatureRSAPSS, crypto.SHA256}, - {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256}, - {rsaCert, []SignatureScheme{PSSWithSHA384, PKCS1WithSHA1}, VersionTLS13, PSSWithSHA384, signatureRSAPSS, crypto.SHA384}, - {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, - {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS12, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, - {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS13, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, - {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS12, Ed25519, signatureEd25519, directSigning}, - {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS13, Ed25519, signatureEd25519, directSigning}, + {rsaCert, []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, VersionTLS12, "", PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256}, + {rsaCert, []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, VersionTLS12, "tlssha1=1", PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {rsaCert, []SignatureScheme{PKCS1WithSHA512, PKCS1WithSHA1}, VersionTLS12, "", PKCS1WithSHA512, signaturePKCS1v15, crypto.SHA512}, + {rsaCert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, "", PSSWithSHA256, signatureRSAPSS, crypto.SHA256}, + {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, "", PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256}, + {rsaCert, []SignatureScheme{PSSWithSHA384, PKCS1WithSHA1}, VersionTLS13, "", PSSWithSHA384, signatureRSAPSS, crypto.SHA384}, + {rsaCert, []SignatureScheme{PKCS1WithSHA1, PSSWithSHA384}, VersionTLS13, "", PSSWithSHA384, signatureRSAPSS, crypto.SHA384}, + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1, ECDSAWithP256AndSHA256}, VersionTLS12, "", ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12, "tlssha1=1", ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS12, "", ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS13, "", ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS12, "", Ed25519, signatureEd25519, directSigning}, + {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS13, "", Ed25519, signatureEd25519, directSigning}, // TLS 1.2 without signature_algorithms extension - {rsaCert, nil, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, - {ecdsaCert, nil, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + {rsaCert, nil, VersionTLS12, "tlssha1=1", PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {ecdsaCert, nil, VersionTLS12, "tlssha1=1", ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, // TLS 1.2 does not restrict the ECDSA curve (our ecdsaCert is P-256) - {ecdsaCert, []SignatureScheme{ECDSAWithP384AndSHA384}, VersionTLS12, ECDSAWithP384AndSHA384, signatureECDSA, crypto.SHA384}, + {ecdsaCert, []SignatureScheme{ECDSAWithP384AndSHA384}, VersionTLS12, "", ECDSAWithP384AndSHA384, signatureECDSA, crypto.SHA384}, } for testNo, test := range tests { + if fips140tls.Required() && test.expectedHash == crypto.SHA1 { + t.Logf("skipping test[%d] - not compatible with TLS FIPS mode", testNo) + continue + } + savedGODEBUG := os.Getenv("GODEBUG") + os.Setenv("GODEBUG", savedGODEBUG+","+test.godebug) + sigAlg, err := selectSignatureScheme(test.tlsVersion, test.cert, test.peerSigAlgs) if err != nil { t.Errorf("test[%d]: unexpected selectSignatureScheme error: %v", testNo, err) @@ -74,6 +89,8 @@ func TestSignatureSelection(t *testing.T) { if test.expectedHash != hashFunc { t.Errorf("test[%d]: expected hash function %#x, got %#x", testNo, test.expectedHash, hashFunc) } + + os.Setenv("GODEBUG", savedGODEBUG) } brokenCert := &Certificate{ @@ -110,6 +127,11 @@ func TestSignatureSelection(t *testing.T) { {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS13}, // The key can be too small for the hash. {rsaCert, []SignatureScheme{PSSWithSHA512}, VersionTLS12}, + // SHA-1 requires tlssha1=1 + {rsaCert, []SignatureScheme{PKCS1WithSHA1}, VersionTLS12}, + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12}, + {rsaCert, nil, VersionTLS12}, + {ecdsaCert, nil, VersionTLS12}, } for testNo, test := range badTests { @@ -153,7 +175,7 @@ func TestLegacyTypeAndHash(t *testing.T) { // TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms // have valid type and hash information. func TestSupportedSignatureAlgorithms(t *testing.T) { - for _, sigAlg := range supportedSignatureAlgorithms() { + for _, sigAlg := range supportedSignatureAlgorithms(VersionTLS12) { sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg) if err != nil { t.Errorf("%v: unexpected error: %v", sigAlg, err) diff --git a/crypto/tls/bogo_config.json b/crypto/tls/bogo_config.json index 2363dd5d659..ed3fc6ec3d6 100644 --- a/crypto/tls/bogo_config.json +++ b/crypto/tls/bogo_config.json @@ -8,11 +8,11 @@ "TLS-ECH-Client-Rejected-OverrideName-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled", "TLS-ECH-Client-Reject-TLS12-NoFalseStart": "We won't attempt to negotiate 1.2 if ECH is enabled", "TLS-ECH-Client-TLS12SessionTicket": "We won't attempt to negotiate 1.2 if ECH is enabled", - "TLS-ECH-Client-TLS12SessionID": "We won't attempt to negotiate 1.2 if ECH is enabled", + "TLS-ECH-Client-TLS12SessionID": "We won't attempt to negotiate 1.2 if ECH is enabled, and we don't support session ID resumption", "TLS-ECH-Client-Reject-ResumeInnerSession-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled (we could possibly test this if we had the ability to indicate not to send ECH on resumption?)", - "TLS-ECH-Client-Reject-EarlyDataRejected": "We don't support switiching out ECH configs with this level of granularity", + "TLS-ECH-Client-Reject-EarlyDataRejected": "Go does not support early (0-RTT) data", "TLS-ECH-Client-NoNPN": "We don't support NPN", @@ -30,67 +30,61 @@ "TLS-ECH-Client-NoSupportedConfigs": "We don't support fallback to cleartext when there are no valid ECH configs", "TLS-ECH-Client-SkipInvalidPublicName": "We don't support fallback to cleartext when there are no valid ECH configs", + "TLS-ECH-Server-EarlyData": "Go does not support early (0-RTT) data", + "TLS-ECH-Server-EarlyDataRejected": "Go does not support early (0-RTT) data", - "*ECH-Server*": "no ECH server support", + "MLKEMKeyShareIncludedSecond": "BoGo wants us to order the key shares based on its preference, but we don't support that", + "MLKEMKeyShareIncludedThird": "BoGo wants us to order the key shares based on its preference, but we don't support that", + "PostQuantumNotEnabledByDefaultInClients": "We do enable it by default!", + "*-Kyber-TLS13": "We don't support Kyber, only ML-KEM (BoGo bug ignoring AllCurves?)", + + "*-RSA_PKCS1_SHA256_LEGACY-TLS13": "We don't support the legacy PKCS#1 v1.5 codepoint for TLS 1.3", + "*-Verify-RSA_PKCS1_SHA256_LEGACY-TLS12": "Likewise, we don't know how to handle it in TLS 1.2, so we send the wrong alert", + "*-VerifyDefault-*": "Our signature algorithms are not configurable, so there is no difference between default and supported", + "Ed25519DefaultDisable-*": "We support Ed25519 by default", + "NoCommonSignatureAlgorithms-TLS12-Fallback": "We don't support the legacy RSA exchange (without tlsrsakex=1)", + + "*_SHA1-TLS12": "We don't support SHA-1 in TLS 1.2 (without tlssha1=1)", + "Agree-Digest-SHA1": "We don't support SHA-1 in TLS 1.2 (without tlssha1=1)", + "ServerAuth-SHA1-Fallback*": "We don't support SHA-1 in TLS 1.2 (without tlssha1=1), so we fail if there are no signature_algorithms", + + "Agree-Digest-SHA256": "We select signature algorithms in peer preference order. We should consider changing this.", + + "V2ClientHello-*": "We don't support SSLv2", "SendV2ClientHello*": "We don't support SSLv2", "*QUIC*": "No QUIC support", "Compliance-fips*": "No FIPS", "*DTLS*": "No DTLS", "SendEmptyRecords*": "crypto/tls doesn't implement spam protections", "SendWarningAlerts*": "crypto/tls doesn't implement spam protections", + "SendUserCanceledAlerts-TooMany-TLS13": "crypto/tls doesn't implement spam protections", "TooManyKeyUpdates": "crypto/tls doesn't implement spam protections (TODO: I think?)", "KyberNotEnabledByDefaultInClients": "crypto/tls intentionally enables it", "JustConfiguringKyberWorks": "we always send a X25519 key share with Kyber", "KyberKeyShareIncludedSecond": "we always send the Kyber key share first", "KyberKeyShareIncludedThird": "we always send the Kyber key share first", - "SkipNewSessionTicket": "TODO confusing? maybe bug", - "SendUserCanceledAlerts*": "TODO may be a real bug?", - "GREASE-Server-TLS13": "TODO ???", - "GarbageCertificate*": "TODO ask davidben, alertDecode vs alertBadCertificate", + "GREASE-Server-TLS13": "We don't send GREASE extensions", "SendBogusAlertType": "sending wrong alert type", - "EchoTLS13CompatibilitySessionID": "TODO reject compat session ID", "*Client-P-224*": "no P-224 support", "*Server-P-224*": "no P-224 support", "CurveID-Resume*": "unexposed curveID is not stored in the ticket yet", + "BadRSAClientKeyExchange-4": "crypto/tls doesn't check the version number in the premaster secret - see processClientKeyExchange comment", + "BadRSAClientKeyExchange-5": "crypto/tls doesn't check the version number in the premaster secret - see processClientKeyExchange comment", + "SupportTicketsWithSessionID": "We don't support session ID resumption", + "ResumeTLS12SessionID-TLS13": "We don't support session ID resumption", + "TrustAnchors-*": "We don't support draft-beck-tls-trust-anchor-ids", + "PAKE-Extension-*": "We don't support PAKE", + "*TicketFlags": "We don't support draft-ietf-tls-tlsflags", + "CheckLeafCurve": "TODO: first pass, this should be fixed", - "DisabledCurve-HelloRetryRequest-TLS13": "TODO: first pass, this should be fixed", - "UnsupportedCurve": "TODO: first pass, this should be fixed", - "SupportTicketsWithSessionID": "TODO: first pass, this should be fixed", - "NoNullCompression-TLS12": "TODO: first pass, this should be fixed", "KeyUpdate-RequestACK": "TODO: first pass, this should be fixed", - "TLS13-HRR-InvalidCompressionMethod": "TODO: first pass, this should be fixed", - "InvalidCompressionMethod": "TODO: first pass, this should be fixed", - "TLS-TLS12-RSA_WITH_AES_128_GCM_SHA256-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS1-RSA_WITH_AES_128_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS11-RSA_WITH_AES_128_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS12-RSA_WITH_AES_128_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS12-RSA_WITH_AES_256_GCM_SHA384-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS1-RSA_WITH_AES_256_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS11-RSA_WITH_AES_256_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS12-RSA_WITH_AES_256_CBC_SHA-LargeRecord": "TODO: first pass, this should be fixed", - "TLS-TLS12-ECDHE_RSA_WITH_AES_128_CBC_SHA256-LargeRecord": "TODO: first pass, this should be fixed", - "RequireAnyClientCertificate-TLS1": "TODO: first pass, this should be fixed", - "RequireAnyClientCertificate-TLS11": "TODO: first pass, this should be fixed", - "RequireAnyClientCertificate-TLS12": "TODO: first pass, this should be fixed", - "ClientHelloVersionTooHigh": "TODO: first pass, this should be fixed", - "MinorVersionTolerance": "TODO: first pass, this should be fixed", - "IgnoreClientVersionOrder": "TODO: first pass, this should be fixed", "SupportedVersionSelection-TLS12": "TODO: first pass, this should be fixed", - "MajorVersionTolerance": "TODO: first pass, this should be fixed", - "DuplicateExtensionServer-TLS-TLS1": "TODO: first pass, this should be fixed", - "DuplicateExtensionClient-TLS-TLS1": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS1": "TODO: first pass, this should be fixed", "TicketSessionIDLength-33-TLS-TLS1": "TODO: first pass, this should be fixed", - "DuplicateExtensionServer-TLS-TLS11": "TODO: first pass, this should be fixed", - "DuplicateExtensionClient-TLS-TLS11": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS11": "TODO: first pass, this should be fixed", "TicketSessionIDLength-33-TLS-TLS11": "TODO: first pass, this should be fixed", - "DuplicateExtensionServer-TLS-TLS12": "TODO: first pass, this should be fixed", - "DuplicateExtensionClient-TLS-TLS12": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS12": "TODO: first pass, this should be fixed", "TicketSessionIDLength-33-TLS-TLS12": "TODO: first pass, this should be fixed", - "DuplicateExtensionClient-TLS-TLS13": "TODO: first pass, this should be fixed", - "DuplicateExtensionServer-TLS-TLS13": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS13": "TODO: first pass, this should be fixed", "RenegotiationInfo-Forbidden-TLS13": "TODO: first pass, this should be fixed", "EMS-Forbidden-TLS13": "TODO: first pass, this should be fixed", @@ -107,19 +101,6 @@ "Resume-Server-OmitPSKsOnSecondClientHello": "TODO: first pass, this should be fixed", "Renegotiate-Server-Forbidden": "TODO: first pass, this should be fixed", "Renegotiate-Client-Forbidden-1": "TODO: first pass, this should be fixed", - "Client-Sign-RSA_PKCS1_SHA1-TLS13": "TODO: first pass, this should be fixed", - "Client-Sign-RSA_PKCS1_SHA256-TLS13": "TODO: first pass, this should be fixed", - "Client-Sign-RSA_PKCS1_SHA384-TLS13": "TODO: first pass, this should be fixed", - "Client-Sign-RSA_PKCS1_SHA512-TLS13": "TODO: first pass, this should be fixed", - "Client-Sign-ECDSA_SHA1-TLS13": "TODO: first pass, this should be fixed", - "Client-Sign-ECDSA_P224_SHA256-TLS13": "TODO: first pass, this should be fixed", - "ClientAuth-NoFallback-TLS13": "TODO: first pass, this should be fixed", - "ClientAuth-NoFallback-ECDSA": "TODO: first pass, this should be fixed", - "ClientAuth-NoFallback-RSA": "TODO: first pass, this should be fixed", - "ECDSACurveMismatch-Verify-TLS13": "TODO: first pass, this should be fixed", - "Ed25519DefaultDisable-NoAdvertise": "TODO: first pass, this should be fixed", - "Ed25519DefaultDisable-NoAccept": "TODO: first pass, this should be fixed", - "NoCommonSignatureAlgorithms-TLS12-Fallback": "TODO: first pass, this should be fixed", "UnknownExtension-Client": "TODO: first pass, this should be fixed", "UnknownUnencryptedExtension-Client-TLS13": "TODO: first pass, this should be fixed", "UnofferedExtension-Client-TLS13": "TODO: first pass, this should be fixed", @@ -127,7 +108,6 @@ "SendClientVersion-RSA": "TODO: first pass, this should be fixed", "NoCommonCurves": "TODO: first pass, this should be fixed", "PointFormat-EncryptedExtensions-TLS13": "TODO: first pass, this should be fixed", - "PointFormat-Client-MissingUncompressed": "TODO: first pass, this should be fixed", "TLS13-SendNoKEMModesWithPSK-Server": "TODO: first pass, this should be fixed", "TLS13-DuplicateTicketEarlyDataSupport": "TODO: first pass, this should be fixed", "Basic-Client-NoTicket-TLS-Sync": "TODO: first pass, this should be fixed", @@ -173,7 +153,6 @@ "TrailingMessageData-TLS13-ClientCertificate-TLS": "TODO: first pass, this should be fixed", "TrailingMessageData-TLS13-ClientCertificateVerify-TLS": "TODO: first pass, this should be fixed", "TrailingMessageData-TLS13-ServerCertificate-TLS": "TODO: first pass, this should be fixed", - "ResumeTLS12SessionID-TLS13": "TODO: first pass, this should be fixed", "SkipEarlyData-TLS13": "TODO: first pass, this should be fixed", "DuplicateKeyShares-TLS13": "TODO: first pass, this should be fixed", "Server-TooLongSessionID-TLS13": "TODO: first pass, this should be fixed", @@ -228,6 +207,21 @@ "EarlyData-Server-BadFinished-TLS13": "TODO: first pass, this should be fixed", "EarlyData-UnexpectedHandshake-Server-TLS13": "TODO: first pass, this should be fixed", "EarlyData-CipherMismatch-Client-TLS13": "TODO: first pass, this should be fixed", - "Resume-Server-UnofferedCipher-TLS13": "TODO: first pass, this should be fixed" + + "Resume-Server-UnofferedCipher-TLS13": "TODO: first pass, this should be fixed", + "GarbageCertificate-Server-TLS13": "TODO: 2025/06 BoGo update, should be fixed", + "WrongMessageType-TLS13-ClientCertificate-TLS": "TODO: 2025/06 BoGo update, should be fixed", + "KeyUpdate-Requested": "TODO: 2025/06 BoGo update, should be fixed", + "AppDataBeforeTLS13KeyChange-*": "TODO: 2025/06 BoGo update, should be fixed" + }, + "AllCurves": [ + 23, + 24, + 25, + 29, + 4588 + ], + "ErrorMap": { + ":ECH_REJECTED:": ["tls: server rejected ECH"] } } diff --git a/crypto/tls/bogo_shim_notunix_test.go b/crypto/tls/bogo_shim_notunix_test.go new file mode 100644 index 00000000000..2dcb5c09dfd --- /dev/null +++ b/crypto/tls/bogo_shim_notunix_test.go @@ -0,0 +1,11 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !unix || wasm + +package tls + +func pauseProcess() { + panic("-wait-for-debugger not supported on this OS") +} diff --git a/crypto/tls/bogo_shim_test.go b/crypto/tls/bogo_shim_test.go index 4352cf38a8e..a4f313e6b43 100644 --- a/crypto/tls/bogo_shim_test.go +++ b/crypto/tls/bogo_shim_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package tls import ( @@ -7,14 +11,10 @@ import ( "encoding/pem" "flag" "fmt" - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/internal/byteorder" - "github.com/runZeroInc/excrypto/internal/testenv" "io" "log" "net" "os" - "os/exec" "path/filepath" "runtime" "slices" @@ -22,6 +22,10 @@ import ( "strings" "testing" + "github.com/runZeroInc/excrypto/crypto/internal/cryptotest" + "github.com/runZeroInc/excrypto/crypto/internal/fips140deps/byteorder" + "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/internal/testenv" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" ) @@ -31,8 +35,10 @@ var ( isHandshakerSupported = flag.Bool("is-handshaker-supported", false, "") - keyfile = flag.String("key-file", "", "") - certfile = flag.String("cert-file", "", "") + keyfile = flag.String("key-file", "", "") + certfile = flag.String("cert-file", "", "") + ocspResponse = flagBase64("ocsp-response", "") + signingPrefs = flagIntSlice("signing-prefs", "") trustCert = flag.String("trust-cert", "", "") @@ -51,13 +57,17 @@ var ( resumeCount = flag.Int("resume-count", 0, "") - curves = flagStringSlice("curves", "") + curves = flagIntSlice("curves", "") expectedCurve = flag.String("expect-curve-id", "", "") + verifyPrefs = flagIntSlice("verify-prefs", "") + expectedSigAlg = flag.String("expect-peer-signature-algorithm", "", "") + expectedPeerSigAlg = flagIntSlice("expect-peer-verify-pref", "") + shimID = flag.Uint64("shim-id", 0, "") _ = flag.Bool("ipv6", false, "") - echConfigListB64 = flag.String("ech-config-list", "", "") + echConfigList = flagBase64("ech-config-list", "") expectECHAccepted = flag.Bool("expect-ech-accept", false, "") expectHRR = flag.Bool("expect-hrr", false, "") expectNoHRR = flag.Bool("expect-no-hrr", false, "") @@ -67,18 +77,21 @@ var ( _ = flag.Bool("expect-no-ech-name-override", false, "") _ = flag.String("expect-ech-name-override", "", "") _ = flag.Bool("reverify-on-resume", false, "") - onResumeECHConfigListB64 = flag.String("on-resume-ech-config-list", "", "") + onResumeECHConfigList = flagBase64("on-resume-ech-config-list", "") _ = flag.Bool("on-resume-expect-reject-early-data", false, "") onResumeExpectECHAccepted = flag.Bool("on-resume-expect-ech-accept", false, "") _ = flag.Bool("on-resume-expect-no-ech-name-override", false, "") expectedServerName = flag.String("expect-server-name", "", "") + echServerConfig = flagStringSlice("ech-server-config", "") + echServerKey = flagStringSlice("ech-server-key", "") + echServerRetryConfig = flagStringSlice("ech-is-retry-config", "") expectSessionMiss = flag.Bool("expect-session-miss", false, "") - _ = flag.Bool("enable-early-data", false, "") - _ = flag.Bool("on-resume-expect-accept-early-data", false, "") - _ = flag.Bool("expect-ticket-supports-early-data", false, "") - onResumeShimWritesFirst = flag.Bool("on-resume-shim-writes-first", false, "") + _ = flag.Bool("enable-early-data", false, "") + _ = flag.Bool("on-resume-expect-accept-early-data", false, "") + _ = flag.Bool("expect-ticket-supports-early-data", false, "") + _ = flag.Bool("on-resume-shim-writes-first", false, "") advertiseALPN = flag.String("advertise-alpn", "", "") expectALPN = flag.String("expect-alpn", "", "") @@ -91,22 +104,69 @@ var ( verifyPeer = flag.Bool("verify-peer", false, "") _ = flag.Bool("use-custom-verify-callback", false, "") + + waitForDebugger = flag.Bool("wait-for-debugger", false, "") ) type stringSlice []string func flagStringSlice(name, usage string) *stringSlice { - f := &stringSlice{} + f := new(stringSlice) + flag.Var(f, name, usage) + return f +} + +func (saf *stringSlice) String() string { + return strings.Join(*saf, ",") +} + +func (saf *stringSlice) Set(s string) error { + *saf = append(*saf, s) + return nil +} + +type intSlice []int64 + +func flagIntSlice(name, usage string) *intSlice { + f := new(intSlice) + flag.Var(f, name, usage) + return f +} + +func (sf *intSlice) String() string { + return strings.Join(strings.Split(fmt.Sprint(*sf), " "), ",") +} + +func (sf *intSlice) Set(s string) error { + i, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + *sf = append(*sf, i) + return nil +} + +type base64Flag []byte + +func flagBase64(name, usage string) *base64Flag { + f := new(base64Flag) flag.Var(f, name, usage) return f } -func (saf stringSlice) String() string { - return strings.Join(saf, ",") +func (f *base64Flag) String() string { + return base64.StdEncoding.EncodeToString(*f) } -func (saf stringSlice) Set(s string) error { - saf = append(saf, s) +func (f *base64Flag) Set(s string) error { + if *f != nil { + return fmt.Errorf("multiple base64 values not supported") + } + b, err := base64.StdEncoding.DecodeString(s) + if err != nil { + return err + } + *f = b return nil } @@ -116,6 +176,14 @@ func bogoShim() { return } + fmt.Printf("BoGo shim flags: %q", os.Args[1:]) + + // Test with both the default and insecure cipher suites. + var ciphersuites []uint16 + for _, s := range append(CipherSuites(), InsecureCipherSuites()...) { + ciphersuites = append(ciphersuites, s.ID) + } + cfg := &Config{ ServerName: "test", @@ -124,6 +192,8 @@ func bogoShim() { ClientSessionCache: NewLRUClientSessionCache(0), + CipherSuites: ciphersuites, + GetConfigForClient: func(chi *ClientHelloInfo) (*Config, error) { if *expectAdvertisedALPN != "" { @@ -201,7 +271,39 @@ func bogoShim() { if err != nil { log.Fatalf("load key-file err: %s", err) } - cfg.Certificates = []Certificate{pair} + for _, id := range *signingPrefs { + pair.SupportedSignatureAlgorithms = append(pair.SupportedSignatureAlgorithms, SignatureScheme(id)) + } + pair.OCSPStaple = *ocspResponse + // Use Get[Client]Certificate to force the use of the certificate, which + // more closely matches the BoGo expectations (e.g. handshake failure if + // no client certificates are compatible). + cfg.GetCertificate = func(chi *ClientHelloInfo) (*Certificate, error) { + if *expectedPeerSigAlg != nil { + if len(chi.SignatureSchemes) != len(*expectedPeerSigAlg) { + return nil, fmt.Errorf("unexpected signature algorithms: got %s, want %v", chi.SignatureSchemes, *expectedPeerSigAlg) + } + for i := range *expectedPeerSigAlg { + if chi.SignatureSchemes[i] != SignatureScheme((*expectedPeerSigAlg)[i]) { + return nil, fmt.Errorf("unexpected signature algorithms: got %s, want %v", chi.SignatureSchemes, *expectedPeerSigAlg) + } + } + } + return &pair, nil + } + cfg.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) { + if *expectedPeerSigAlg != nil { + if len(cri.SignatureSchemes) != len(*expectedPeerSigAlg) { + return nil, fmt.Errorf("unexpected signature algorithms: got %s, want %v", cri.SignatureSchemes, *expectedPeerSigAlg) + } + for i := range *expectedPeerSigAlg { + if cri.SignatureSchemes[i] != SignatureScheme((*expectedPeerSigAlg)[i]) { + return nil, fmt.Errorf("unexpected signature algorithms: got %s, want %v", cri.SignatureSchemes, *expectedPeerSigAlg) + } + } + } + return &pair, nil + } } if *trustCert != "" { pool := x509.NewCertPool() @@ -225,32 +327,49 @@ func bogoShim() { cfg.ClientAuth = VerifyClientCertIfGiven } - if *echConfigListB64 != "" { - echConfigList, err := base64.StdEncoding.DecodeString(*echConfigListB64) - if err != nil { - log.Fatalf("parse ech-config-list err: %s", err) - } - cfg.EncryptedClientHelloConfigList = echConfigList + if *echConfigList != nil { + cfg.EncryptedClientHelloConfigList = *echConfigList cfg.MinVersion = VersionTLS13 } - if len(*curves) != 0 { - for _, curveStr := range *curves { - id, err := strconv.Atoi(curveStr) - if err != nil { - log.Fatalf("failed to parse curve id %q: %s", curveStr, err) - } + if *curves != nil { + for _, id := range *curves { cfg.CurvePreferences = append(cfg.CurvePreferences, CurveID(id)) } } - for i := 0; i < *resumeCount+1; i++ { - if i > 0 && (*onResumeECHConfigListB64 != "") { - echConfigList, err := base64.StdEncoding.DecodeString(*onResumeECHConfigListB64) + if *verifyPrefs != nil { + for _, id := range *verifyPrefs { + testingOnlySupportedSignatureAlgorithms = append(testingOnlySupportedSignatureAlgorithms, SignatureScheme(id)) + } + } + + if *echServerConfig != nil { + if len(*echServerConfig) != len(*echServerKey) || len(*echServerConfig) != len(*echServerRetryConfig) { + log.Fatal("-ech-server-config, -ech-server-key, and -ech-is-retry-config mismatch") + } + + for i, c := range *echServerConfig { + configBytes, err := base64.StdEncoding.DecodeString(c) + if err != nil { + log.Fatalf("parse ech-server-config err: %s", err) + } + privBytes, err := base64.StdEncoding.DecodeString((*echServerKey)[i]) if err != nil { - log.Fatalf("parse ech-config-list err: %s", err) + log.Fatalf("parse ech-server-key err: %s", err) } - cfg.EncryptedClientHelloConfigList = echConfigList + + cfg.EncryptedClientHelloKeys = append(cfg.EncryptedClientHelloKeys, EncryptedClientHelloKey{ + Config: configBytes, + PrivateKey: privBytes, + SendAsRetry: (*echServerRetryConfig)[i] == "1", + }) + } + } + + for i := 0; i < *resumeCount+1; i++ { + if i > 0 && *onResumeECHConfigList != nil { + cfg.EncryptedClientHelloConfigList = *onResumeECHConfigList } conn, err := net.Dial("tcp", net.JoinHostPort("localhost", *port)) @@ -261,7 +380,7 @@ func bogoShim() { // Write the shim ID we were passed as a little endian uint64 shimIDBytes := make([]byte, 8) - byteorder.LePutUint64(shimIDBytes, *shimID) + byteorder.LEPutUint64(shimIDBytes, *shimID) if _, err := conn.Write(shimIDBytes); err != nil { log.Fatalf("failed to write shim id: %s", err) } @@ -279,6 +398,12 @@ func bogoShim() { } } + // If we were instructed to wait for a debugger, then send SIGSTOP to ourselves. + // When the debugger attaches it will continue the process. + if *waitForDebugger { + pauseProcess() + } + for { buf := make([]byte, 500) var n int @@ -294,10 +419,16 @@ func bogoShim() { break } } - if err != nil && err != io.EOF { + if err != io.EOF { + // Flush the TLS conn and then perform a graceful shutdown of the + // TCP connection to avoid the runner side hitting an unexpected + // write error before it has processed the alert we may have + // generated for the error condition. + orderlyShutdown(tlsConn) + retryErr, ok := err.(*ECHRejectionError) if !ok { - log.Fatalf("unexpected error type returned: %v", err) + log.Fatal(err) } if *expectNoECHRetryConfigs && len(retryErr.RetryConfigList) > 0 { log.Fatalf("expected no ECH retry configs, got some") @@ -362,25 +493,57 @@ func bogoShim() { if err != nil { log.Fatalf("failed to parse -expect-curve-id: %s", err) } - if tlsConn.curveID != CurveID(expectedCurveID) { + if cs.CurveID != CurveID(expectedCurveID) { log.Fatalf("unexpected curve id: want %d, got %d", expectedCurveID, tlsConn.curveID) } } + + // TODO: implement testingOnlyPeerSignatureAlgorithm on resumption. + if *expectedSigAlg != "" && !cs.DidResume { + expectedSigAlgID, err := strconv.Atoi(*expectedSigAlg) + if err != nil { + log.Fatalf("failed to parse -expect-peer-signature-algorithm: %s", err) + } + if cs.testingOnlyPeerSignatureAlgorithm != SignatureScheme(expectedSigAlgID) { + log.Fatalf("unexpected peer signature algorithm: want %s, got %s", SignatureScheme(expectedSigAlgID), cs.testingOnlyPeerSignatureAlgorithm) + } + } } } -func TestBogoSuite(t *testing.T) { - testenv.SkipIfShortAndSlow(t) - testenv.MustHaveExternalNetwork(t) - testenv.MustHaveGoRun(t) - testenv.MustHaveExec(t) +// If the test case produces an error, we don't want to immediately close the +// TCP connection after generating an alert. The runner side may try to write +// additional data to the connection before it reads the alert. If the conn +// has already been torn down, then these writes will produce an unexpected +// broken pipe err and fail the test. +func orderlyShutdown(tlsConn *Conn) { + // Flush any pending alert data + tlsConn.flush() + + netConn := tlsConn.NetConn() + tcpConn := netConn.(*net.TCPConn) + tcpConn.CloseWrite() + + // Read and discard any data that was sent by the peer. + buf := make([]byte, maxPlaintext) + for { + n, err := tcpConn.Read(buf) + if n == 0 || err != nil { + break + } + } + tcpConn.CloseRead() +} + +func TestBogoSuite(t *testing.T) { if testing.Short() { t.Skip("skipping in short mode") } if testenv.Builder() != "" && runtime.GOOS == "windows" { t.Skip("#66913: windows network connections are flakey on builders") } + skipFIPS(t) // In order to make Go test caching work as expected, we stat the // bogo_config.json file, so that the Go testing hooks know that it is @@ -394,18 +557,8 @@ func TestBogoSuite(t *testing.T) { if *bogoLocalDir != "" { bogoDir = *bogoLocalDir } else { - const boringsslModVer = "v0.0.0-20240523173554-273a920f84e8" - output, err := exec.Command("go", "mod", "download", "-json", "boringssl.googlesource.com/boringssl.git@"+boringsslModVer).CombinedOutput() - if err != nil { - t.Fatalf("failed to download boringssl: %s", err) - } - var j struct { - Dir string - } - if err := json.Unmarshal(output, &j); err != nil { - t.Fatalf("failed to parse 'go mod download' output: %s", err) - } - bogoDir = j.Dir + const boringsslModVer = "v0.0.0-20250620172916-f51d8b099832" + bogoDir = cryptotest.FetchModule(t, "boringssl.googlesource.com/boringssl.git", boringsslModVer) } cwd, err := os.Getwd() @@ -429,11 +582,7 @@ func TestBogoSuite(t *testing.T) { args = append(args, fmt.Sprintf("-test=%s", *bogoFilter)) } - goCmd, err := testenv.GoTool() - if err != nil { - t.Fatal(err) - } - cmd := exec.Command(goCmd, args...) + cmd := testenv.Command(t, testenv.GoToolPath(t), args...) out := &strings.Builder{} cmd.Stderr = out cmd.Dir = filepath.Join(bogoDir, "ssl/test/runner") @@ -461,22 +610,38 @@ func TestBogoSuite(t *testing.T) { // are present in the output. They are only checked if -bogo-filter // was not passed. assertResults := map[string]string{ - "CurveTest-Client-Kyber-TLS13": "PASS", - "CurveTest-Server-Kyber-TLS13": "PASS", + "CurveTest-Client-MLKEM-TLS13": "PASS", + "CurveTest-Server-MLKEM-TLS13": "PASS", + + // Various signature algorithm tests checking that we enforce our + // preferences on the peer. + "ClientAuth-Enforced": "PASS", + "ServerAuth-Enforced": "PASS", + "ClientAuth-Enforced-TLS13": "PASS", + "ServerAuth-Enforced-TLS13": "PASS", + "VerifyPreferences-Advertised": "PASS", + "VerifyPreferences-Enforced": "PASS", + "Client-TLS12-NoSign-RSA_PKCS1_MD5_SHA1": "PASS", + "Server-TLS12-NoSign-RSA_PKCS1_MD5_SHA1": "PASS", + "Client-TLS13-NoSign-RSA_PKCS1_MD5_SHA1": "PASS", + "Server-TLS13-NoSign-RSA_PKCS1_MD5_SHA1": "PASS", } for name, result := range results.Tests { // This is not really the intended way to do this... but... it works? t.Run(name, func(t *testing.T) { if result.Actual == "FAIL" && result.IsUnexpected { - t.Fatal(result.Error) + t.Fail() + } + if result.Error != "" { + t.Log(result.Error) } - if expectedResult, ok := assertResults[name]; ok && expectedResult != result.Actual { - t.Fatalf("unexpected result: got %s, want %s", result.Actual, assertResults[name]) + if exp, ok := assertResults[name]; ok && exp != result.Actual { + t.Errorf("unexpected result: got %s, want %s", result.Actual, exp) } delete(assertResults, name) if result.Actual == "SKIP" { - t.Skip() + t.SkipNow() } }) } diff --git a/crypto/tls/bogo_shim_unix_test.go b/crypto/tls/bogo_shim_unix_test.go new file mode 100644 index 00000000000..3b5f5f92c22 --- /dev/null +++ b/crypto/tls/bogo_shim_unix_test.go @@ -0,0 +1,18 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix && !wasm + +package tls + +import ( + "os" + "syscall" +) + +func pauseProcess() { + pid := os.Getpid() + process, _ := os.FindProcess(pid) + process.Signal(syscall.SIGSTOP) +} diff --git a/crypto/tls/cache.go b/crypto/tls/cache.go index a7cd6ccfbb1..58a72805357 100644 --- a/crypto/tls/cache.go +++ b/crypto/tls/cache.go @@ -5,81 +5,23 @@ package tls import ( - "github.com/runZeroInc/excrypto/crypto/x509" "runtime" "sync" - "sync/atomic" -) - -type cacheEntry struct { - refs atomic.Int64 - cert *x509.Certificate -} + "weak" -// certCache implements an intern table for reference counted x509.Certificates, -// implemented in a similar fashion to BoringSSL's CRYPTO_BUFFER_POOL. This -// allows for a single x509.Certificate to be kept in memory and referenced from -// multiple Conns. Returned references should not be mutated by callers. Certificates -// are still safe to use after they are removed from the cache. -// -// Certificates are returned wrapped in an activeCert struct that should be held by -// the caller. When references to the activeCert are freed, the number of references -// to the certificate in the cache is decremented. Once the number of references -// reaches zero, the entry is evicted from the cache. -// -// The main difference between this implementation and CRYPTO_BUFFER_POOL is that -// CRYPTO_BUFFER_POOL is a more generic structure which supports blobs of data, -// rather than specific structures. Since we only care about x509.Certificates, -// certCache is implemented as a specific cache, rather than a generic one. -// -// See https://boringssl.googlesource.com/boringssl/+/master/include/openssl/pool.h -// and https://boringssl.googlesource.com/boringssl/+/master/crypto/pool/pool.c -// for the BoringSSL reference. -type certCache struct { - sync.Map -} + "github.com/runZeroInc/excrypto/crypto/x509" +) -var globalCertCache = new(certCache) +// weakCertCache provides a cache of *x509.Certificates, allowing multiple +// connections to reuse parsed certificates, instead of re-parsing the +// certificate for every connection, which is an expensive operation. +type weakCertCache struct{ sync.Map } -// activeCert is a handle to a certificate held in the cache. Once there are -// no alive activeCerts for a given certificate, the certificate is removed -// from the cache by a finalizer. -type activeCert struct { - cert *x509.Certificate -} - -// active increments the number of references to the entry, wraps the -// certificate in the entry in an activeCert, and sets the finalizer. -// -// Note that there is a race between active and the finalizer set on the -// returned activeCert, triggered if active is called after the ref count is -// decremented such that refs may be > 0 when evict is called. We consider this -// safe, since the caller holding an activeCert for an entry that is no longer -// in the cache is fine, with the only side effect being the memory overhead of -// there being more than one distinct reference to a certificate alive at once. -func (cc *certCache) active(e *cacheEntry) *activeCert { - e.refs.Add(1) - a := &activeCert{e.cert} - runtime.SetFinalizer(a, func(_ *activeCert) { - if e.refs.Add(-1) == 0 { - cc.evict(e) +func (wcc *weakCertCache) newCert(der []byte) (*x509.Certificate, error) { + if entry, ok := wcc.Load(string(der)); ok { + if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { + return v, nil } - }) - return a -} - -// evict removes a cacheEntry from the cache. -func (cc *certCache) evict(e *cacheEntry) { - cc.Delete(string(e.cert.Raw)) -} - -// newCert returns a x509.Certificate parsed from der. If there is already a copy -// of the certificate in the cache, a reference to the existing certificate will -// be returned. Otherwise, a fresh certificate will be added to the cache, and -// the reference returned. The returned reference should not be mutated. -func (cc *certCache) newCert(der []byte) (*activeCert, error) { - if entry, ok := cc.Load(string(der)); ok { - return cc.active(entry.(*cacheEntry)), nil } cert, err := x509.ParseCertificate(der) @@ -87,9 +29,17 @@ func (cc *certCache) newCert(der []byte) (*activeCert, error) { return nil, err } - entry := &cacheEntry{cert: cert} - if entry, loaded := cc.LoadOrStore(string(der), entry); loaded { - return cc.active(entry.(*cacheEntry)), nil + wp := weak.Make(cert) + if entry, loaded := wcc.LoadOrStore(string(der), wp); !loaded { + runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), entry) }, any(string(der))) + } else if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { + return v, nil + } else { + if wcc.CompareAndSwap(string(der), entry, wp) { + runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), wp) }, any(string(der))) + } } - return cc.active(entry), nil + return cert, nil } + +var globalCertCache = new(weakCertCache) diff --git a/crypto/tls/cache_test.go b/crypto/tls/cache_test.go index 2846734195d..75a0508ec0d 100644 --- a/crypto/tls/cache_test.go +++ b/crypto/tls/cache_test.go @@ -1,63 +1,60 @@ -// Copyright 2022 The Go Authors. All rights reserved. +// Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. - package tls import ( "encoding/pem" - "fmt" "runtime" "testing" "time" ) -func TestCertCache(t *testing.T) { - cc := certCache{} +func TestWeakCertCache(t *testing.T) { + wcc := weakCertCache{} p, _ := pem.Decode([]byte(rsaCertPEM)) if p == nil { t.Fatal("Failed to decode certificate") } - certA, err := cc.newCert(p.Bytes) + certA, err := wcc.newCert(p.Bytes) if err != nil { t.Fatalf("newCert failed: %s", err) } - certB, err := cc.newCert(p.Bytes) + certB, err := wcc.newCert(p.Bytes) if err != nil { t.Fatalf("newCert failed: %s", err) } - if certA.cert != certB.cert { + if certA != certB { t.Fatal("newCert returned a unique reference for a duplicate certificate") } - if entry, ok := cc.Load(string(p.Bytes)); !ok { + if _, ok := wcc.Load(string(p.Bytes)); !ok { t.Fatal("cache does not contain expected entry") - } else { - if refs := entry.(*cacheEntry).refs.Load(); refs != 2 { - t.Fatalf("unexpected number of references: got %d, want 2", refs) - } } - timeoutRefCheck := func(t *testing.T, key string, count int64) { + timeoutRefCheck := func(t *testing.T, key string, present bool) { t.Helper() - c := time.After(4 * time.Second) + timeout := time.After(4 * time.Second) for { select { - case <-c: + case <-timeout: t.Fatal("timed out waiting for expected ref count") default: - e, ok := cc.Load(key) - if !ok && count != 0 { - t.Fatal("cache does not contain expected key") - } else if count == 0 && !ok { - return - } - - if e.(*cacheEntry).refs.Load() == count { + _, ok := wcc.Load(key) + if ok == present { return } } + // Explicitly yield to the scheduler. + // + // On single-threaded platforms like js/wasm a busy-loop might + // never call into the scheduler for the full timeout, meaning + // that if we arrive here and the cleanup hasn't already run, + // we'll simply loop until the timeout. Busy-loops put us at the + // mercy of the Go scheduler, making this test fragile on some + // platforms. + runtime.Gosched() } } @@ -68,7 +65,7 @@ func TestCertCache(t *testing.T) { certA = nil runtime.GC() - timeoutRefCheck(t, string(p.Bytes), 1) + timeoutRefCheck(t, string(p.Bytes), true) // Keep certB alive until at least now, so that we can // purposefully nil it and force the finalizer to be @@ -77,41 +74,5 @@ func TestCertCache(t *testing.T) { certB = nil runtime.GC() - timeoutRefCheck(t, string(p.Bytes), 0) -} - -func BenchmarkCertCache(b *testing.B) { - p, _ := pem.Decode([]byte(rsaCertPEM)) - if p == nil { - b.Fatal("Failed to decode certificate") - } - - cc := certCache{} - b.ReportAllocs() - b.ResetTimer() - // We expect that calling newCert additional times after - // the initial call should not cause additional allocations. - for extra := 0; extra < 4; extra++ { - b.Run(fmt.Sprint(extra), func(b *testing.B) { - actives := make([]*activeCert, extra+1) - b.ResetTimer() - for i := 0; i < b.N; i++ { - var err error - actives[0], err = cc.newCert(p.Bytes) - if err != nil { - b.Fatal(err) - } - for j := 0; j < extra; j++ { - actives[j+1], err = cc.newCert(p.Bytes) - if err != nil { - b.Fatal(err) - } - } - for j := 0; j < extra+1; j++ { - actives[j] = nil - } - runtime.GC() - } - }) - } + timeoutRefCheck(t, string(p.Bytes), false) } diff --git a/crypto/tls/cipher_suites.go b/crypto/tls/cipher_suites.go index e80933319f1..41dcb6c0b70 100644 --- a/crypto/tls/cipher_suites.go +++ b/crypto/tls/cipher_suites.go @@ -6,37 +6,41 @@ package tls import ( "fmt" - "hash" "runtime" _ "unsafe" // for linkname + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/internal/cpu" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/des" "github.com/runZeroInc/excrypto/crypto/hmac" "github.com/runZeroInc/excrypto/crypto/internal/boring" + fipsaes "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/aes/gcm" "github.com/runZeroInc/excrypto/crypto/rc4" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" - "github.com/runZeroInc/excrypto/internal/cpu" - "github.com/runZeroInc/excrypto/x/crypto/chacha20poly1305" + "golang.org/x/crypto/chacha20poly1305" ) // CipherSuite is a TLS cipher suite. Note that most functions in this package // accept and expose cipher suite IDs instead of this type. type CipherSuite struct { - ID uint16 `json:"id"` - Name string `json:"name"` + ID uint16 + Name string // Supported versions is the list of TLS protocol versions that can // negotiate this cipher suite. - SupportedVersions []uint16 `json:"supported_versions"` + SupportedVersions []uint16 // Insecure is true if the cipher suite has known security issues // due to its primitives, design, or implementation. - Insecure bool `json:"insecure"` + Insecure bool } var ( @@ -77,8 +81,8 @@ func CipherSuites() []*CipherSuite { // Most applications should not use the cipher suites in this list, and should // only use those returned by [CipherSuites]. func InsecureCipherSuites() []*CipherSuite { - // This list includes RC4, CBC_SHA256, and 3DES cipher suites. See - // cipherSuitesPreferenceOrder for details. + // This list includes legacy RSA kex, RC4, CBC_SHA256, and 3DES cipher + // suites. See cipherSuitesPreferenceOrder for details. return []*CipherSuite{ {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, @@ -234,7 +238,7 @@ var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map. // - Anything else comes before CBC_SHA256 // // SHA-256 variants of the CBC ciphersuites don't implement any Lucky13 -// countermeasures. See http://www.isg.rhul.ac.uk/tls/Lucky13.html and +// countermeasures. See https://www.isg.rhul.ac.uk/tls/Lucky13.html and // https://www.imperialviolet.org/2013/02/04/luckythirteen.html. // // - Anything else comes before 3DES @@ -366,15 +370,13 @@ var tdesCiphers = map[uint16]bool{ } var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + // Keep in sync with crypto/internal/fips140/aes/gcm.supportsAESGCM. + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && - (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH + hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X + hasAESGCMHardwareSupport = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X || hasGCMAsmPPC64 ) var aesgcmCiphers = map[uint16]bool{ @@ -388,9 +390,13 @@ var aesgcmCiphers = map[uint16]bool{ TLS_AES_256_GCM_SHA384: true, } -// aesgcmPreferred returns whether the first known cipher in the preference list -// is an AES-GCM cipher, implying the peer has hardware support for it. -func aesgcmPreferred(ciphers []uint16) bool { +// isAESGCMPreferred returns whether we have hardware support for AES-GCM, and the +// first known cipher in the peer's preference list is an AES-GCM cipher, +// implying the peer also has hardware support for it. +func isAESGCMPreferred(ciphers []uint16) bool { + if !hasAESGCMHardwareSupport { + return false + } for _, cID := range ciphers { if c := cipherSuiteByID(cID); c != nil { return aesgcmCiphers[cID] @@ -524,7 +530,7 @@ func aeadAESGCM(key, noncePrefix []byte) aead { aead, err = boring.NewGCMTLS(aes) } else { boring.Unreachable() - aead, err = cipher.NewGCM(aes) + aead, err = gcm.NewGCMForTLS12(aes.(*fipsaes.Block)) } if err != nil { panic(err) @@ -558,7 +564,7 @@ func aeadAESGCMTLS13(key, nonceMask []byte) aead { aead, err = boring.NewGCMTLS13(aes) } else { boring.Unreachable() - aead, err = cipher.NewGCM(aes) + aead, err = gcm.NewGCMForTLS13(aes.(*fipsaes.Block)) } if err != nil { panic(err) diff --git a/crypto/tls/common.go b/crypto/tls/common.go index 659d5a424fb..757fecc1837 100644 --- a/crypto/tls/common.go +++ b/crypto/tls/common.go @@ -15,24 +15,24 @@ import ( "fmt" "io" "math/big" + + rtls "crypto/tls" "net" "slices" "strings" "sync" "time" - - rtls "crypto/tls" + _ "unsafe" // for linkname "github.com/runZeroInc/excrypto/crypto" - "github.com/runZeroInc/excrypto/internal/godebug" - "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/ed25519" "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/sha512" - + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/internal/godebug" ) const ( @@ -178,17 +178,21 @@ const ( type CurveID uint16 const ( - CurveP256 CurveID = 23 - CurveP384 CurveID = 24 - CurveP521 CurveID = 25 - X25519 CurveID = 29 - - // Experimental codepoint for X25519Kyber768Draft00, specified in - // draft-tls-westerbaan-xyber768d00-03. Not exported, as support might be - // removed in the future. - x25519Kyber768Draft00 CurveID = 0x6399 // X25519Kyber768Draft00 + CurveP256 CurveID = 23 + CurveP384 CurveID = 24 + CurveP521 CurveID = 25 + X25519 CurveID = 29 + X25519MLKEM768 CurveID = 4588 ) +func isTLS13OnlyKeyExchange(curve CurveID) bool { + return curve == X25519MLKEM768 +} + +func isPQKeyExchange(curve CurveID) bool { + return curve == X25519MLKEM768 +} + // TLS 1.3 Key Share. See RFC 8446, Section 4.2.8. type keyShare struct { group CurveID @@ -423,6 +427,11 @@ type ConnectionState struct { // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256). CipherSuite uint16 + // CurveID is the key exchange mechanism used for the connection. The name + // refers to elliptic curves for legacy reasons, see [CurveID]. If a legacy + // RSA key exchange is used, this value is zero. + CurveID CurveID + // NegotiatedProtocol is the application protocol negotiated with ALPN. NegotiatedProtocol string @@ -481,6 +490,10 @@ type ConnectionState struct { // testingOnlyDidHRR is true if a HelloRetryRequest was sent/received. testingOnlyDidHRR bool + // testingOnlyPeerSignatureAlgorithm is the signature algorithm used by the + // peer to sign the handshake. It is not set for resumed connections. + testingOnlyPeerSignatureAlgorithm SignatureScheme + // testingOnlyCurveID is the selected CurveID, or zero if an RSA exchanges // is performed. testingOnlyCurveID CurveID @@ -546,34 +559,26 @@ const ( // NoClientCert indicates that no client certificate should be requested // during the handshake, and if any certificates are sent they will not // be verified. - NoClientCert ClientAuthType = 0 + NoClientCert ClientAuthType = iota // RequestClientCert indicates that a client certificate should be requested // during the handshake, but does not require that the client send any // certificates. - RequestClientCert ClientAuthType = 1 + RequestClientCert // RequireAnyClientCert indicates that a client certificate should be requested // during the handshake, and that at least one certificate is required to be // sent by the client, but that certificate is not required to be valid. - RequireAnyClientCert ClientAuthType = 2 + RequireAnyClientCert // VerifyClientCertIfGiven indicates that a client certificate should be requested // during the handshake, but does not require that the client sends a // certificate. If the client does send a certificate it is required to be // valid. - VerifyClientCertIfGiven ClientAuthType = 3 + VerifyClientCertIfGiven // RequireAndVerifyClientCert indicates that a client certificate should be requested // during the handshake, and that at least one valid certificate is required // to be sent by the client. - RequireAndVerifyClientCert ClientAuthType = 4 + RequireAndVerifyClientCert ) -func (authType *ClientAuthType) String() string { - if name, ok := clientAuthTypeNames[int(*authType)]; ok { - return name - } - - return "unknown" -} - func (authType *ClientAuthType) MarshalJSON() ([]byte, error) { return []byte(`"` + authType.String() + `"`), nil } @@ -696,9 +701,12 @@ type ClientHelloInfo struct { // client is using SNI (see RFC 4366, Section 3.1). ServerName string - // SupportedCurves lists the elliptic curves supported by the client. - // SupportedCurves is set only if the Supported Elliptic Curves - // Extension is being used (see RFC 4492, Section 5.1.1). + // SupportedCurves lists the key exchange mechanisms supported by the + // client. It was renamed to "supported groups" in TLS 1.3, see RFC 8446, + // Section 4.2.7 and [CurveID]. + // + // SupportedCurves may be nil in TLS 1.2 and lower if the Supported Elliptic + // Curves Extension is not being used (see RFC 4492, Section 5.1.1). SupportedCurves []CurveID // SupportedPoints lists the point formats supported by the client. @@ -726,7 +734,7 @@ type ClientHelloInfo struct { SupportedVersions []uint16 // Extensions lists the IDs of the extensions presented by the client - // in the client hello. + // in the ClientHello. Extensions []uint16 // Conn is the underlying net.Conn for the connection. Do not read @@ -946,7 +954,7 @@ func (config *Config) MarshalJSON() ([]byte, error) { aux.ClientCAs = config.ClientCAs aux.InsecureSkipVerify = config.InsecureSkipVerify - ciphers := config.cipherSuites() + ciphers := config.cipherSuites(true) aux.CipherSuites = make([]CipherSuite, len(ciphers)) for i, aCipher := range ciphers { aux.CipherSuites[i] = CipherSuite{ID: aCipher} @@ -1280,14 +1288,15 @@ type Config struct { // which is currently TLS 1.3. MaxVersion uint16 - // CurvePreferences contains the elliptic curves that will be used in - // an ECDHE handshake, in preference order. If empty, the default will - // be used. The client will use the first preference as the type for - // its key share in TLS 1.3. This may change in the future. + // CurvePreferences contains a set of supported key exchange mechanisms. + // The name refers to elliptic curves for legacy reasons, see [CurveID]. + // The order of the list is ignored, and key exchange mechanisms are chosen + // from this list using an internal preference order. If empty, the default + // will be used. // - // From Go 1.23, the default includes the X25519Kyber768Draft00 hybrid + // From Go 1.24, the default includes the [X25519MLKEM768] hybrid // post-quantum key exchange. To disable it, set CurvePreferences explicitly - // or use the GODEBUG=tlskyber=0 environment variable. + // or use the GODEBUG=tlsmlkem=0 environment variable. CurvePreferences []CurveID // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. @@ -1377,8 +1386,10 @@ type Config struct { // EncryptedClientHelloConfigList is a serialized ECHConfigList. If // provided, clients will attempt to connect to servers using Encrypted - // Client Hello (ECH) using one of the provided ECHConfigs. Servers - // currently ignore this field. + // Client Hello (ECH) using one of the provided ECHConfigs. + // + // Servers do not use this field. In order to configure ECH for servers, see + // the EncryptedClientHelloKeys field. // // If the list contains no valid ECH configs, the handshake will fail // and return an error. @@ -1387,7 +1398,7 @@ type Config struct { // be VersionTLS13. // // When EncryptedClientHelloConfigList is set, the handshake will only - // succeed if ECH is sucessfully negotiated. If the server rejects ECH, + // succeed if ECH is successfully negotiated. If the server rejects ECH, // an ECHRejectionError error will be returned, which may contain a new // ECHConfigList that the server suggests using. // @@ -1396,9 +1407,11 @@ type Config struct { EncryptedClientHelloConfigList []byte // EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is - // rejected, in order to verify the ECH provider certificate in the outer - // Client Hello. If it returns a non-nil error, the handshake is aborted and - // that error results. + // rejected by the remote server, in order to verify the ECH provider + // certificate in the outer ClientHello. If it returns a non-nil error, the + // handshake is aborted and that error results. + // + // On the server side this field is not used. // // Unlike VerifyPeerCertificate and VerifyConnection, normal certificate // verification will not be performed before calling @@ -1410,6 +1423,37 @@ type Config struct { // when ECH is rejected, even if set, and InsecureSkipVerify is ignored. EncryptedClientHelloRejectionVerify func(ConnectionState) error + // GetEncryptedClientHelloKeys, if not nil, is called when by a server when + // a client attempts ECH. + // + // If GetEncryptedClientHelloKeys is not nil, [EncryptedClientHelloKeys] is + // ignored. + // + // If GetEncryptedClientHelloKeys returns an error, the handshake will be + // aborted and the error will be returned. Otherwise, + // GetEncryptedClientHelloKeys must return a non-nil slice of + // [EncryptedClientHelloKey] that represents the acceptable ECH keys. + // + // For further details, see [EncryptedClientHelloKeys]. + GetEncryptedClientHelloKeys func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) + + // EncryptedClientHelloKeys are the ECH keys to use when a client + // attempts ECH. + // + // If EncryptedClientHelloKeys is set, MinVersion, if set, must be + // VersionTLS13. + // + // If a client attempts ECH, but it is rejected by the server, the server + // will send a list of configs to retry based on the set of + // EncryptedClientHelloKeys which have the SendAsRetry field set. + // + // If GetEncryptedClientHelloKeys is non-nil, EncryptedClientHelloKeys is + // ignored. + // + // On the client side, this field is ignored. In order to configure ECH for + // clients, see the EncryptedClientHelloConfigList field. + EncryptedClientHelloKeys []EncryptedClientHelloKey + // mutex protects sessionTicketKeys and autoSessionTicketKeys. mutex sync.RWMutex // sessionTicketKeys contains zero or more ticket keys. If set, it means @@ -1423,6 +1467,24 @@ type Config struct { autoSessionTicketKeys []ticketKey } +// EncryptedClientHelloKey holds a private key that is associated +// with a specific ECH config known to a client. +type EncryptedClientHelloKey struct { + // Config should be a marshalled ECHConfig associated with PrivateKey. This + // must match the config provided to clients byte-for-byte. The config + // should only specify the DHKEM(X25519, HKDF-SHA256) KEM ID (0x0020), the + // HKDF-SHA256 KDF ID (0x0001), and a subset of the following AEAD IDs: + // AES-128-GCM (0x0001), AES-256-GCM (0x0002), ChaCha20Poly1305 (0x0003). + Config []byte + // PrivateKey should be a marshalled private key. Currently, we expect + // this to be the output of [ecdh.PrivateKey.Bytes]. + PrivateKey []byte + // SendAsRetry indicates if Config should be sent as part of the list of + // retry configs when ECH is requested by the client but rejected by the + // server. + SendAsRetry bool +} + const ( // ticketKeyLifetime is how long a ticket key remains valid and can be used to // resume a client connection. @@ -1473,8 +1535,11 @@ func (c *Config) Clone() *Config { Time: c.Time, Certificates: c.Certificates, NameToCertificate: c.NameToCertificate, + GetCertificate: c.GetCertificate, GetClientCertificate: c.GetClientCertificate, GetConfigForClient: c.GetConfigForClient, + GetEncryptedClientHelloKeys: c.GetEncryptedClientHelloKeys, + VerifyPeerCertificate: c.VerifyPeerCertificate, VerifyConnection: c.VerifyConnection, RootCAs: c.RootCAs, NextProtos: c.NextProtos, @@ -1492,18 +1557,14 @@ func (c *Config) Clone() *Config { MinVersion: c.MinVersion, MaxVersion: c.MaxVersion, CurvePreferences: c.CurvePreferences, + DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, + Renegotiation: c.Renegotiation, + KeyLogWriter: c.KeyLogWriter, EncryptedClientHelloConfigList: c.EncryptedClientHelloConfigList, EncryptedClientHelloRejectionVerify: c.EncryptedClientHelloRejectionVerify, + EncryptedClientHelloKeys: c.EncryptedClientHelloKeys, sessionTicketKeys: c.sessionTicketKeys, autoSessionTicketKeys: c.autoSessionTicketKeys, - ExplicitCurvePreferences: c.ExplicitCurvePreferences, - ClientFingerprintConfiguration: c.ClientFingerprintConfiguration, - CertsOnly: c.CertsOnly, - GetCertificate: c.GetCertificate, - DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, - VerifyPeerCertificate: c.VerifyPeerCertificate, - KeyLogWriter: c.KeyLogWriter, - Renegotiation: c.Renegotiation, } } @@ -1556,6 +1617,7 @@ func (c *Config) ticketKeys(configForClient *Config) []ticketKey { if configForClient != nil { configForClient.mutex.RLock() if configForClient.SessionTicketsDisabled { + configForClient.mutex.RUnlock() return nil } configForClient.initLegacySessionTicketKeyRLocked() @@ -1649,20 +1711,28 @@ func (c *Config) time() time.Time { return t() } -func (c *Config) cipherSuites() []uint16 { +func (c *Config) cipherSuites(aesGCMPreferred bool) []uint16 { + var cipherSuites []uint16 if c.CipherSuites == nil { - if needFIPS() { - return defaultCipherSuitesFIPS - } - return defaultCipherSuites() + cipherSuites = defaultCipherSuites(aesGCMPreferred) + } else { + cipherSuites = supportedCipherSuites(aesGCMPreferred) + cipherSuites = slices.DeleteFunc(cipherSuites, func(id uint16) bool { + return !slices.Contains(c.CipherSuites, id) + }) } - if needFIPS() { - cipherSuites := slices.Clone(c.CipherSuites) - return slices.DeleteFunc(cipherSuites, func(id uint16) bool { - return !slices.Contains(defaultCipherSuitesFIPS, id) + if fips140tls.Required() { + cipherSuites = slices.DeleteFunc(cipherSuites, func(id uint16) bool { + return !slices.Contains(allowedCipherSuitesFIPS, id) }) } - return c.CipherSuites + return cipherSuites +} + +// supportedCipherSuites returns the supported TLS 1.0–1.2 cipher suites in an +// undefined order. For preference ordering, use [Config.cipherSuites]. +func (c *Config) supportedCipherSuites() []uint16 { + return c.cipherSuites(false) } var supportedVersions = []uint16{ @@ -1679,10 +1749,12 @@ const roleServer = false var tls10server = godebug.New("tls10server") +// supportedVersions returns the list of supported TLS versions, sorted from +// highest to lowest (and hence also in preference order). func (c *Config) supportedVersions(isClient bool) []uint16 { versions := make([]uint16, 0, len(supportedVersions)) for _, v := range supportedVersions { - if needFIPS() && !slices.Contains(defaultSupportedVersionsFIPS, v) { + if fips140tls.Required() && !slices.Contains(allowedSupportedVersionsFIPS, v) { continue } if (c == nil || c.MinVersion == 0) && v < VersionTLS12 { @@ -1727,45 +1799,34 @@ func supportedVersionsFromMax(maxVersion uint16) []uint16 { } func (c *Config) curvePreferences(version uint16) []CurveID { - var curvePreferences []CurveID + curvePreferences := defaultCurvePreferences() + if fips140tls.Required() { + curvePreferences = slices.DeleteFunc(curvePreferences, func(x CurveID) bool { + return !slices.Contains(allowedCurvePreferencesFIPS, x) + }) + } if c != nil && len(c.CurvePreferences) != 0 { - curvePreferences = slices.Clone(c.CurvePreferences) - if needFIPS() { - return slices.DeleteFunc(curvePreferences, func(c CurveID) bool { - return !slices.Contains(defaultCurvePreferencesFIPS, c) - }) - } - } else if needFIPS() { - curvePreferences = slices.Clone(defaultCurvePreferencesFIPS) - } else { - curvePreferences = defaultCurvePreferences() + curvePreferences = slices.DeleteFunc(curvePreferences, func(x CurveID) bool { + return !slices.Contains(c.CurvePreferences, x) + }) } if version < VersionTLS13 { - return slices.DeleteFunc(curvePreferences, func(c CurveID) bool { - return c == x25519Kyber768Draft00 - }) + curvePreferences = slices.DeleteFunc(curvePreferences, isTLS13OnlyKeyExchange) } return curvePreferences } func (c *Config) supportsCurve(version uint16, curve CurveID) bool { - for _, cc := range c.curvePreferences(version) { - if cc == curve { - return true - } - } - return false + return slices.Contains(c.curvePreferences(version), curve) } // mutualVersion returns the protocol version to use given the advertised -// versions of the peer. Priority is given to the peer preference order. +// versions of the peer. The highest supported version is preferred. func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) { supportedVersions := c.supportedVersions(isClient) - for _, peerVersion := range peerVersions { - for _, v := range supportedVersions { - if v == peerVersion { - return v, true - } + for _, v := range supportedVersions { + if slices.Contains(peerVersions, v) { + return v, true } } return 0, false @@ -1778,6 +1839,8 @@ func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bo // // Do not remove or change the type signature. // See go.dev/issue/67401. +// +//go:linkname errNoCertificates var errNoCertificates = errors.New("tls: no certificates configured") // getCertificate returns the best certificate for the given ClientHelloInfo, @@ -1934,7 +1997,7 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { } // Finally, there needs to be a mutual cipher suite that uses the static // RSA key exchange instead of ECDHE. - rsaCipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool { + rsaCipherSuite := selectCipherSuite(chi.CipherSuites, config.supportedCipherSuites(), func(c *cipherSuite) bool { if c.flags&suiteECDHE != 0 { return false } @@ -1965,7 +2028,11 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { } // The only signed key exchange we support is ECDHE. - if !supportsECDHE(config, vers, chi.SupportedCurves, chi.SupportedPoints) { + ecdheSupported, err := supportsECDHE(config, vers, chi.SupportedCurves, chi.SupportedPoints) + if err != nil { + return err + } + if !ecdheSupported { return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange")) } @@ -1973,20 +2040,20 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { if priv, ok := c.PrivateKey.(crypto.Signer); ok { switch pub := priv.Public().(type) { case *ecdsa.PublicKey: - var cid CurveID + var curve CurveID switch pub.Curve { case elliptic.P256(): - cid = CurveP256 + curve = CurveP256 case elliptic.P384(): - cid = CurveP384 + curve = CurveP384 case elliptic.P521(): - cid = CurveP521 + curve = CurveP521 default: return supportsRSAFallback(unsupportedCertificateError(c)) } var curveOk bool for _, c := range chi.SupportedCurves { - if c == cid && config.supportsCurve(vers, c) { + if c == curve && config.supportsCurve(vers, c) { curveOk = true break } @@ -2011,7 +2078,7 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { // Make sure that there is a mutually supported cipher suite that works with // this certificate. Cipher suite selection will then apply the logic in // reverse to pick it. See also serverHandshakeState.cipherSuiteOk. - cipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool { + cipherSuite := selectCipherSuite(chi.CipherSuites, config.supportedCipherSuites(), func(c *cipherSuite) bool { if c.flags&suiteECDHE == 0 { return false } @@ -2267,23 +2334,68 @@ func unexpectedMessageError(wanted, got any) error { return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) } -// supportedSignatureAlgorithms returns the supported signature algorithms. -func supportedSignatureAlgorithms() []SignatureScheme { - if !needFIPS() { - return defaultSupportedSignatureAlgorithms +var testingOnlySupportedSignatureAlgorithms []SignatureScheme + +// supportedSignatureAlgorithms returns the supported signature algorithms for +// the given minimum TLS version, to advertise in ClientHello and +// CertificateRequest messages. +func supportedSignatureAlgorithms(minVers uint16) []SignatureScheme { + sigAlgs := defaultSupportedSignatureAlgorithms() + if testingOnlySupportedSignatureAlgorithms != nil { + sigAlgs = slices.Clone(testingOnlySupportedSignatureAlgorithms) } - return defaultSupportedSignatureAlgorithmsFIPS + return slices.DeleteFunc(sigAlgs, func(s SignatureScheme) bool { + return isDisabledSignatureAlgorithm(minVers, s, false) + }) } -func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool { - for _, s := range supportedSignatureAlgorithms { - if s == sigAlg { +var tlssha1 = godebug.New("tlssha1") + +func isDisabledSignatureAlgorithm(version uint16, s SignatureScheme, isCert bool) bool { + if fips140tls.Required() && !slices.Contains(allowedSignatureAlgorithmsFIPS, s) { + return true + } + + // For the _cert extension we include all algorithms, including SHA-1 and + // PKCS#1 v1.5, because it's more likely that something on our side will be + // willing to accept a *-with-SHA1 certificate (e.g. with a custom + // VerifyConnection or by a direct match with the CertPool), than that the + // peer would have a better certificate but is just choosing not to send it. + // crypto/x509 will refuse to verify important SHA-1 signatures anyway. + if isCert { + return false + } + + // TLS 1.3 removed support for PKCS#1 v1.5 and SHA-1 signatures, + // and Go 1.25 removed support for SHA-1 signatures in TLS 1.2. + if version > VersionTLS12 { + sigType, sigHash, _ := typeAndHashFromSignatureScheme(s) + if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { + return true + } + } else if tlssha1.Value() != "1" { + _, sigHash, _ := typeAndHashFromSignatureScheme(s) + if sigHash == crypto.SHA1 { return true } } + return false } +// supportedSignatureAlgorithmsCert returns the supported algorithms for +// signatures in certificates. +func supportedSignatureAlgorithmsCert() []SignatureScheme { + sigAlgs := defaultSupportedSignatureAlgorithms() + return slices.DeleteFunc(sigAlgs, func(s SignatureScheme) bool { + return isDisabledSignatureAlgorithm(0, s, true) + }) +} + +func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool { + return slices.Contains(supportedSignatureAlgorithms, sigAlg) +} + // CertificateVerificationError is returned when certificate verification fails during the handshake. type CertificateVerificationError struct { // UnverifiedCertificates and its contents should not be modified. @@ -2315,3 +2427,42 @@ type ClientCertificateRequest struct { OCSPStapling bool UnknownExtensions [][]byte } + +// fipsAllowedChains returns chains that are allowed to be used in a TLS connection +// based on the current fips140tls enforcement setting. +// +// If fips140tls is not required, the chains are returned as-is with no processing. +// Otherwise, the returned chains are filtered to only those allowed by FIPS 140-3. +// If this results in no chains it returns an error. +func fipsAllowedChains(chains [][]*x509.Certificate) ([][]*x509.Certificate, error) { + if !fips140tls.Required() { + return chains, nil + } + + permittedChains := make([][]*x509.Certificate, 0, len(chains)) + for _, chain := range chains { + if fipsAllowChain(chain) { + permittedChains = append(permittedChains, chain) + } + } + + if len(permittedChains) == 0 { + return nil, errors.New("tls: no FIPS compatible certificate chains found") + } + + return permittedChains, nil +} + +func fipsAllowChain(chain []*x509.Certificate) bool { + if len(chain) == 0 { + return false + } + + for _, cert := range chain { + if !isCertificateAllowedFIPS(cert) { + return false + } + } + + return true +} diff --git a/crypto/tls/common_string.go b/crypto/tls/common_string.go index ef60973bad1..e15dd48838b 100644 --- a/crypto/tls/common_string.go +++ b/crypto/tls/common_string.go @@ -71,13 +71,13 @@ func _() { _ = x[CurveP384-24] _ = x[CurveP521-25] _ = x[X25519-29] - _ = x[x25519Kyber768Draft00-25497] + _ = x[X25519MLKEM768-4588] } const ( _CurveID_name_0 = "CurveP256CurveP384CurveP521" _CurveID_name_1 = "X25519" - _CurveID_name_2 = "X25519Kyber768Draft00" + _CurveID_name_2 = "X25519MLKEM768" ) var ( @@ -91,7 +91,7 @@ func (i CurveID) String() string { return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]] case i == 29: return _CurveID_name_1 - case i == 25497: + case i == 4588: return _CurveID_name_2 default: return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")" @@ -110,4 +110,11 @@ func _() { const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertVerifyClientCertIfGivenRequireAndVerifyClientCert" -var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} \ No newline at end of file +var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} + +func (i ClientAuthType) String() string { + if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) { + return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]] +} diff --git a/crypto/tls/conn.go b/crypto/tls/conn.go index 0bc9278face..f48677e7f92 100644 --- a/crypto/tls/conn.go +++ b/crypto/tls/conn.go @@ -11,13 +11,14 @@ import ( "context" "errors" "fmt" - "hash" "io" "net" "sync" "sync/atomic" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/subtle" "github.com/runZeroInc/excrypto/crypto/x509" @@ -52,12 +53,10 @@ type Conn struct { didHRR bool // whether a HelloRetryRequest was sent/received cipherSuite uint16 curveID CurveID + peerSigAlg SignatureScheme ocspResponse []byte // stapled OCSP response scts [][]byte // signed certificate timestamps from server peerCertificates []*x509.Certificate - // activeCertHandles contains the cache handles to certificates in - // peerCertificates that are used to track active references. - activeCertHandles []*activeCert // verifiedChains contains the certificate chains that we built, as // opposed to the ones presented by the server. verifiedChains [][]*x509.Certificate @@ -750,6 +749,15 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { return c.in.setErrorLocked(io.EOF) } if c.vers == VersionTLS13 { + // TLS 1.3 removed warning-level alerts except for alertUserCanceled + // (RFC 8446, § 6.1). Since at least one major implementation + // (https://bugs.openjdk.org/browse/JDK-8323517) misuses this alert, + // many TLS stacks now ignore it outright when seen in a TLS 1.3 + // handshake (e.g. BoringSSL, NSS, Rustls). + if alert(data[1]) == alertUserCanceled { + // Like TLS 1.2 alertLevelWarning alerts, we drop the record and retry. + return c.retryReadRecord(expectChangeCipherSpec) + } return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) } switch data[0] { @@ -1199,7 +1207,7 @@ func (c *Conn) unmarshalHandshakeMessage(data []byte, transcript transcriptHash) data = append([]byte(nil), data...) if !m.unmarshal(data) { - return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + return nil, c.in.setErrorLocked(c.sendAlert(alertDecodeError)) } if transcript != nil { @@ -1650,8 +1658,8 @@ func (c *Conn) connectionStateLocked() ConnectionState { state.NegotiatedProtocol = c.clientProtocol state.DidResume = c.didResume state.testingOnlyDidHRR = c.didHRR - // c.curveID is not set on TLS 1.0–1.2 resumptions. Fix that before exposing it. - state.testingOnlyCurveID = c.curveID + state.testingOnlyPeerSignatureAlgorithm = c.peerSigAlg + state.CurveID = c.curveID state.NegotiatedProtocolIsMutual = true state.ServerName = c.serverName state.CipherSuite = c.cipherSuite @@ -1661,7 +1669,6 @@ func (c *Conn) connectionStateLocked() ConnectionState { state.OCSPResponse = c.ocspResponse state.ClientCertificateRequested = c.ClientCertificateRequested state.ClientCertificateRequest = c.ClientCertificateRequest - if (!c.didResume || c.extMasterSecret) && c.vers != VersionTLS13 { if c.clientFinishedIsFirst { state.TLSUnique = c.clientFinished[:] diff --git a/crypto/tls/conn_test.go b/crypto/tls/conn_test.go index 5e090a017dc..5fd48d6bd5a 100644 --- a/crypto/tls/conn_test.go +++ b/crypto/tls/conn_test.go @@ -230,6 +230,8 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) { } func TestDynamicRecordSizingWithStreamCipher(t *testing.T) { + skipFIPS(t) // No RC4 in FIPS mode. + config := testConfig.Clone() config.MaxVersion = VersionTLS12 config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} @@ -237,6 +239,8 @@ func TestDynamicRecordSizingWithStreamCipher(t *testing.T) { } func TestDynamicRecordSizingWithCBC(t *testing.T) { + skipFIPS(t) // No CBC cipher suites in defaultCipherSuitesFIPS. + config := testConfig.Clone() config.MaxVersion = VersionTLS12 config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA} diff --git a/crypto/tls/defaults.go b/crypto/tls/defaults.go index 509a9b6c081..d6a01f24c5e 100644 --- a/crypto/tls/defaults.go +++ b/crypto/tls/defaults.go @@ -14,41 +14,52 @@ import ( // Defaults are collected in this file to allow distributions to more easily patch // them to apply local policies. -var tlskyber = godebug.New("tlskyber") +var tlsmlkem = godebug.New("tlsmlkem") +// defaultCurvePreferences is the default set of supported key exchanges, as +// well as the preference order. func defaultCurvePreferences() []CurveID { - if tlskyber.Value() == "0" { + if tlsmlkem.Value() == "0" { return []CurveID{X25519, CurveP256, CurveP384, CurveP521} } - // For now, x25519Kyber768Draft00 must always be followed by X25519. - return []CurveID{x25519Kyber768Draft00, X25519, CurveP256, CurveP384, CurveP521} + return []CurveID{X25519MLKEM768, X25519, CurveP256, CurveP384, CurveP521} } -// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that -// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+ +// defaultSupportedSignatureAlgorithms returns the signature and hash algorithms that +// the code advertises and supports in a TLS 1.2+ ClientHello and in a TLS 1.2+ // CertificateRequest. The two fields are merged to match with TLS 1.3. // Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc. -var defaultSupportedSignatureAlgorithms = []SignatureScheme{ - PSSWithSHA256, - ECDSAWithP256AndSHA256, - Ed25519, - PSSWithSHA384, - PSSWithSHA512, - PKCS1WithSHA256, - PKCS1WithSHA384, - PKCS1WithSHA512, - ECDSAWithP384AndSHA384, - ECDSAWithP521AndSHA512, - PKCS1WithSHA1, - ECDSAWithSHA1, +func defaultSupportedSignatureAlgorithms() []SignatureScheme { + return []SignatureScheme{ + PSSWithSHA256, + ECDSAWithP256AndSHA256, + Ed25519, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + PKCS1WithSHA384, + PKCS1WithSHA512, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, + PKCS1WithSHA1, + ECDSAWithSHA1, + } } var tlsrsakex = godebug.New("tlsrsakex") var tls3des = godebug.New("tls3des") -func defaultCipherSuites() []uint16 { - suites := slices.Clone(cipherSuitesPreferenceOrder) - return slices.DeleteFunc(suites, func(c uint16) bool { +func supportedCipherSuites(aesGCMPreferred bool) []uint16 { + if aesGCMPreferred { + return slices.Clone(cipherSuitesPreferenceOrder) + } else { + return slices.Clone(cipherSuitesPreferenceOrderNoAES) + } +} + +func defaultCipherSuites(aesGCMPreferred bool) []uint16 { + cipherSuites := supportedCipherSuites(aesGCMPreferred) + return slices.DeleteFunc(cipherSuites, func(c uint16) bool { return disabledCipherSuites[c] || tlsrsakex.Value() != "1" && rsaKexCiphers[c] || tls3des.Value() != "1" && tdesCiphers[c] @@ -90,41 +101,3 @@ var defaultCipherSuitesTLS13NoAES = []uint16{ TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, } - -// The FIPS-only policies below match BoringSSL's ssl_policy_fips_202205. - -var defaultSupportedVersionsFIPS = []uint16{ - VersionTLS12, - VersionTLS13, -} - -// defaultCurvePreferencesFIPS are the FIPS-allowed curves, -// in preference order (most preferable first). -var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384} - -// defaultSupportedSignatureAlgorithmsFIPS currently are a subset of -// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. -var defaultSupportedSignatureAlgorithmsFIPS = []SignatureScheme{ - PSSWithSHA256, - PSSWithSHA384, - PSSWithSHA512, - PKCS1WithSHA256, - ECDSAWithP256AndSHA256, - PKCS1WithSHA384, - ECDSAWithP384AndSHA384, - PKCS1WithSHA512, -} - -// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. -var defaultCipherSuitesFIPS = []uint16{ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, -} - -// defaultCipherSuitesTLS13FIPS are the FIPS-allowed cipher suites for TLS 1.3. -var defaultCipherSuitesTLS13FIPS = []uint16{ - TLS_AES_128_GCM_SHA256, - TLS_AES_256_GCM_SHA384, -} diff --git a/crypto/tls/defaults_boring.go b/crypto/tls/defaults_boring.go new file mode 100644 index 00000000000..044ba021f5a --- /dev/null +++ b/crypto/tls/defaults_boring.go @@ -0,0 +1,69 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +package tls + +import ( + "github.com/runZeroInc/excrypto/crypto/ecdsa" + "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/rsa" + "github.com/runZeroInc/excrypto/crypto/x509" +) + +// These Go+BoringCrypto policies mostly match BoringSSL's +// ssl_compliance_policy_fips_202205, which is based on NIST SP 800-52r2. +// https://cs.opensource.google/boringssl/boringssl/+/master:ssl/ssl_lib.cc;l=3289;drc=ea7a88fa +// +// P-521 is allowed per https://go.dev/issue/71757. +// +// They are applied when crypto/tls/fipsonly is imported with GOEXPERIMENT=boringcrypto. + +var ( + allowedSupportedVersionsFIPS = []uint16{ + VersionTLS12, + VersionTLS13, + } + allowedCurvePreferencesFIPS = []CurveID{ + CurveP256, + CurveP384, + CurveP521, + } + allowedSignatureAlgorithmsFIPS = []SignatureScheme{ + PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + ECDSAWithP256AndSHA256, + PKCS1WithSHA384, + ECDSAWithP384AndSHA384, + PKCS1WithSHA512, + ECDSAWithP521AndSHA512, + } + allowedCipherSuitesFIPS = []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + } + allowedCipherSuitesTLS13FIPS = []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + } +) + +func isCertificateAllowedFIPS(c *x509.Certificate) bool { + // The key must be RSA 2048, RSA 3072, RSA 4096, + // or ECDSA P-256, P-384, P-521. + switch k := c.PublicKey.(type) { + case *rsa.PublicKey: + size := k.N.BitLen() + return size == 2048 || size == 3072 || size == 4096 + case *ecdsa.PublicKey: + return k.Curve == elliptic.P256() || k.Curve == elliptic.P384() || k.Curve == elliptic.P521() + } + + return false +} diff --git a/crypto/tls/defaults_fips140.go b/crypto/tls/defaults_fips140.go new file mode 100644 index 00000000000..f1f5ad1cd36 --- /dev/null +++ b/crypto/tls/defaults_fips140.go @@ -0,0 +1,76 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !boringcrypto + +package tls + +import ( + "github.com/runZeroInc/excrypto/crypto/ecdsa" + "github.com/runZeroInc/excrypto/crypto/ed25519" + "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/rsa" + "github.com/runZeroInc/excrypto/crypto/x509" +) + +// These FIPS 140-3 policies allow anything approved by SP 800-140C +// and SP 800-140D, and tested as part of the Go Cryptographic Module. +// +// Notably, not SHA-1, 3DES, RC4, ChaCha20Poly1305, RSA PKCS #1 v1.5 key +// transport, or TLS 1.0—1.1 (because we don't test its KDF). +// +// These are not default lists, but filters to apply to the default or +// configured lists. Missing items are treated as if they were not implemented. +// +// They are applied when the fips140 GODEBUG is "on" or "only". + +var ( + allowedSupportedVersionsFIPS = []uint16{ + VersionTLS12, + VersionTLS13, + } + allowedCurvePreferencesFIPS = []CurveID{ + X25519MLKEM768, + CurveP256, + CurveP384, + CurveP521, + } + allowedSignatureAlgorithmsFIPS = []SignatureScheme{ + PSSWithSHA256, + ECDSAWithP256AndSHA256, + Ed25519, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + PKCS1WithSHA384, + PKCS1WithSHA512, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, + } + allowedCipherSuitesFIPS = []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + } + allowedCipherSuitesTLS13FIPS = []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + } +) + +func isCertificateAllowedFIPS(c *x509.Certificate) bool { + switch k := c.PublicKey.(type) { + case *rsa.PublicKey: + return k.N.BitLen() >= 2048 + case *ecdsa.PublicKey: + return k.Curve == elliptic.P256() || k.Curve == elliptic.P384() || k.Curve == elliptic.P521() + case ed25519.PublicKey: + return true + default: + return false + } +} diff --git a/crypto/tls/ech.go b/crypto/tls/ech.go index e30329ecabc..fa5d2035ce9 100644 --- a/crypto/tls/ech.go +++ b/crypto/tls/ech.go @@ -5,13 +5,28 @@ package tls import ( + "bytes" "errors" - "github.com/runZeroInc/excrypto/crypto/internal/hpke" + "fmt" + "slices" "strings" + "github.com/runZeroInc/excrypto/crypto/internal/hpke" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" ) +// sortedSupportedAEADs is just a sorted version of hpke.SupportedAEADS. +// We need this so that when we insert them into ECHConfigs the ordering +// is stable. +var sortedSupportedAEADs []uint16 + +func init() { + for aeadID := range hpke.SupportedAEADs { + sortedSupportedAEADs = append(sortedSupportedAEADs, aeadID) + } + slices.Sort(sortedSupportedAEADs) +} + type echCipher struct { KDFID uint16 AEADID uint16 @@ -38,86 +53,111 @@ type echConfig struct { Extensions []echExtension } -var errMalformedECHConfig = errors.New("tls: malformed ECHConfigList") +var errMalformedECHConfigList = errors.New("tls: malformed ECHConfigList") + +type echConfigErr struct { + field string +} + +func (e *echConfigErr) Error() string { + if e.field == "" { + return "tls: malformed ECHConfig" + } + return fmt.Sprintf("tls: malformed ECHConfig, invalid %s field", e.field) +} + +func parseECHConfig(enc []byte) (skip bool, ec echConfig, err error) { + s := cryptobyte.String(enc) + ec.raw = []byte(enc) + if !s.ReadUint16(&ec.Version) { + return false, echConfig{}, &echConfigErr{"version"} + } + if !s.ReadUint16(&ec.Length) { + return false, echConfig{}, &echConfigErr{"length"} + } + if len(ec.raw) < int(ec.Length)+4 { + return false, echConfig{}, &echConfigErr{"length"} + } + ec.raw = ec.raw[:ec.Length+4] + if ec.Version != extensionEncryptedClientHello { + s.Skip(int(ec.Length)) + return true, echConfig{}, nil + } + if !s.ReadUint8(&ec.ConfigID) { + return false, echConfig{}, &echConfigErr{"config_id"} + } + if !s.ReadUint16(&ec.KemID) { + return false, echConfig{}, &echConfigErr{"kem_id"} + } + if !readUint16LengthPrefixed(&s, &ec.PublicKey) { + return false, echConfig{}, &echConfigErr{"public_key"} + } + var cipherSuites cryptobyte.String + if !s.ReadUint16LengthPrefixed(&cipherSuites) { + return false, echConfig{}, &echConfigErr{"cipher_suites"} + } + for !cipherSuites.Empty() { + var c echCipher + if !cipherSuites.ReadUint16(&c.KDFID) { + return false, echConfig{}, &echConfigErr{"cipher_suites kdf_id"} + } + if !cipherSuites.ReadUint16(&c.AEADID) { + return false, echConfig{}, &echConfigErr{"cipher_suites aead_id"} + } + ec.SymmetricCipherSuite = append(ec.SymmetricCipherSuite, c) + } + if !s.ReadUint8(&ec.MaxNameLength) { + return false, echConfig{}, &echConfigErr{"maximum_name_length"} + } + var publicName cryptobyte.String + if !s.ReadUint8LengthPrefixed(&publicName) { + return false, echConfig{}, &echConfigErr{"public_name"} + } + ec.PublicName = publicName + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) { + return false, echConfig{}, &echConfigErr{"extensions"} + } + for !extensions.Empty() { + var e echExtension + if !extensions.ReadUint16(&e.Type) { + return false, echConfig{}, &echConfigErr{"extensions type"} + } + if !extensions.ReadUint16LengthPrefixed((*cryptobyte.String)(&e.Data)) { + return false, echConfig{}, &echConfigErr{"extensions data"} + } + ec.Extensions = append(ec.Extensions, e) + } + + return false, ec, nil +} // parseECHConfigList parses a draft-ietf-tls-esni-18 ECHConfigList, returning a // slice of parsed ECHConfigs, in the same order they were parsed, or an error // if the list is malformed. func parseECHConfigList(data []byte) ([]echConfig, error) { s := cryptobyte.String(data) - // Skip the length prefix var length uint16 if !s.ReadUint16(&length) { - return nil, errMalformedECHConfig + return nil, errMalformedECHConfigList } if length != uint16(len(data)-2) { - return nil, errMalformedECHConfig + return nil, errMalformedECHConfigList } var configs []echConfig for len(s) > 0 { - var ec echConfig - ec.raw = []byte(s) - if !s.ReadUint16(&ec.Version) { - return nil, errMalformedECHConfig - } - if !s.ReadUint16(&ec.Length) { - return nil, errMalformedECHConfig - } - if len(ec.raw) < int(ec.Length)+4 { - return nil, errMalformedECHConfig - } - ec.raw = ec.raw[:ec.Length+4] - if ec.Version != extensionEncryptedClientHello { - s.Skip(int(ec.Length)) - continue - } - if !s.ReadUint8(&ec.ConfigID) { - return nil, errMalformedECHConfig - } - if !s.ReadUint16(&ec.KemID) { - return nil, errMalformedECHConfig + if len(s) < 4 { + return nil, errors.New("tls: malformed ECHConfig") } - if !s.ReadUint16LengthPrefixed((*cryptobyte.String)(&ec.PublicKey)) { - return nil, errMalformedECHConfig + configLen := uint16(s[2])<<8 | uint16(s[3]) + skip, ec, err := parseECHConfig(s) + if err != nil { + return nil, err } - var cipherSuites cryptobyte.String - if !s.ReadUint16LengthPrefixed(&cipherSuites) { - return nil, errMalformedECHConfig + s = s[configLen+4:] + if !skip { + configs = append(configs, ec) } - for !cipherSuites.Empty() { - var c echCipher - if !cipherSuites.ReadUint16(&c.KDFID) { - return nil, errMalformedECHConfig - } - if !cipherSuites.ReadUint16(&c.AEADID) { - return nil, errMalformedECHConfig - } - ec.SymmetricCipherSuite = append(ec.SymmetricCipherSuite, c) - } - if !s.ReadUint8(&ec.MaxNameLength) { - return nil, errMalformedECHConfig - } - var publicName cryptobyte.String - if !s.ReadUint8LengthPrefixed(&publicName) { - return nil, errMalformedECHConfig - } - ec.PublicName = publicName - var extensions cryptobyte.String - if !s.ReadUint16LengthPrefixed(&extensions) { - return nil, errMalformedECHConfig - } - for !extensions.Empty() { - var e echExtension - if !extensions.ReadUint16(&e.Type) { - return nil, errMalformedECHConfig - } - if !extensions.ReadUint16LengthPrefixed((*cryptobyte.String)(&e.Data)) { - return nil, errMalformedECHConfig - } - ec.Extensions = append(ec.Extensions, e) - } - - configs = append(configs, ec) } return configs, nil } @@ -195,6 +235,195 @@ func encodeInnerClientHello(inner *clientHelloMsg, maxNameLength int) ([]byte, e return append(h, make([]byte, paddingLen)...), nil } +func skipUint8LengthPrefixed(s *cryptobyte.String) bool { + var skip uint8 + if !s.ReadUint8(&skip) { + return false + } + return s.Skip(int(skip)) +} + +func skipUint16LengthPrefixed(s *cryptobyte.String) bool { + var skip uint16 + if !s.ReadUint16(&skip) { + return false + } + return s.Skip(int(skip)) +} + +type rawExtension struct { + extType uint16 + data []byte +} + +func extractRawExtensions(hello *clientHelloMsg) ([]rawExtension, error) { + s := cryptobyte.String(hello.original) + if !s.Skip(4+2+32) || // header, version, random + !skipUint8LengthPrefixed(&s) || // session ID + !skipUint16LengthPrefixed(&s) || // cipher suites + !skipUint8LengthPrefixed(&s) { // compression methods + return nil, errors.New("tls: malformed outer client hello") + } + var rawExtensions []rawExtension + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) { + return nil, errors.New("tls: malformed outer client hello") + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return nil, errors.New("tls: invalid inner client hello") + } + rawExtensions = append(rawExtensions, rawExtension{extension, extData}) + } + return rawExtensions, nil +} + +func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHelloMsg, error) { + // Reconstructing the inner client hello from its encoded form is somewhat + // complicated. It is missing its header (message type and length), session + // ID, and the extensions may be compressed. Since we need to put the + // extensions back in the same order as they were in the raw outer hello, + // and since we don't store the raw extensions, or the order we parsed them + // in, we need to reparse the raw extensions from the outer hello in order + // to properly insert them into the inner hello. This _should_ result in raw + // bytes which match the hello as it was generated by the client. + innerReader := cryptobyte.String(encoded) + var versionAndRandom, sessionID, cipherSuites, compressionMethods []byte + var extensions cryptobyte.String + if !innerReader.ReadBytes(&versionAndRandom, 2+32) || + !readUint8LengthPrefixed(&innerReader, &sessionID) || + len(sessionID) != 0 || + !readUint16LengthPrefixed(&innerReader, &cipherSuites) || + !readUint8LengthPrefixed(&innerReader, &compressionMethods) || + !innerReader.ReadUint16LengthPrefixed(&extensions) { + return nil, errors.New("tls: invalid inner client hello") + } + + // The specification says we must verify that the trailing padding is all + // zeros. This is kind of weird for TLS messages, where we generally just + // throw away any trailing garbage. + for _, p := range innerReader { + if p != 0 { + return nil, errors.New("tls: invalid inner client hello") + } + } + + rawOuterExts, err := extractRawExtensions(outer) + if err != nil { + return nil, err + } + + recon := cryptobyte.NewBuilder(nil) + recon.AddUint8(typeClientHello) + recon.AddUint24LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(versionAndRandom) + recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(outer.sessionId) + }) + recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(cipherSuites) + }) + recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(compressionMethods) + }) + recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + recon.SetError(errors.New("tls: invalid inner client hello")) + return + } + if extension == extensionECHOuterExtensions { + if !extData.ReadUint8LengthPrefixed(&extData) { + recon.SetError(errors.New("tls: invalid inner client hello")) + return + } + var i int + for !extData.Empty() { + var extType uint16 + if !extData.ReadUint16(&extType) { + recon.SetError(errors.New("tls: invalid inner client hello")) + return + } + if extType == extensionEncryptedClientHello { + recon.SetError(errors.New("tls: invalid outer extensions")) + return + } + for ; i <= len(rawOuterExts); i++ { + if i == len(rawOuterExts) { + recon.SetError(errors.New("tls: invalid outer extensions")) + return + } + if rawOuterExts[i].extType == extType { + break + } + } + recon.AddUint16(rawOuterExts[i].extType) + recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(rawOuterExts[i].data) + }) + } + } else { + recon.AddUint16(extension) + recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { + recon.AddBytes(extData) + }) + } + } + }) + }) + + reconBytes, err := recon.Bytes() + if err != nil { + return nil, err + } + inner := &clientHelloMsg{} + if !inner.unmarshal(reconBytes) { + return nil, errors.New("tls: invalid reconstructed inner client hello") + } + + if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) { + return nil, errInvalidECHExt + } + + hasTLS13 := false + for _, v := range inner.supportedVersions { + // Skip GREASE values (values of the form 0x?A0A). + // GREASE (Generate Random Extensions And Sustain Extensibility) is a mechanism used by + // browsers like Chrome to ensure TLS implementations correctly ignore unknown values. + // GREASE values follow a specific pattern: 0x?A0A, where ? can be any hex digit. + // These values should be ignored when processing supported TLS versions. + if v&0x0F0F == 0x0A0A && v&0xff == v>>8 { + continue + } + + // Ensure at least TLS 1.3 is offered. + if v == VersionTLS13 { + hasTLS13 = true + } else if v < VersionTLS13 { + // Reject if any non-GREASE value is below TLS 1.3, as ECH requires TLS 1.3+. + return nil, errors.New("tls: client sent encrypted_client_hello extension with unsupported versions") + } + } + + if !hasTLS13 { + return nil, errors.New("tls: client sent encrypted_client_hello extension but did not offer TLS 1.3") + } + + return inner, nil +} + +func decryptECHPayload(context *hpke.Recipient, hello, payload []byte) ([]byte, error) { + outerAAD := bytes.Replace(hello[4:], payload, make([]byte, len(payload)), 1) + return context.Open(outerAAD, payload) +} + func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payload []byte) ([]byte, error) { var b cryptobyte.Builder b.AddUint8(0) // outer @@ -206,7 +435,7 @@ func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payl return b.Bytes() } -func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echContext, useKey bool) error { +func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echClientContext, useKey bool) error { var encapKey []byte if useKey { encapKey = ech.encapsulatedKey @@ -281,3 +510,159 @@ type ECHRejectionError struct { func (e *ECHRejectionError) Error() string { return "tls: server rejected ECH" } + +var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension") +var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension") + +type echExtType uint8 + +const ( + innerECHExt echExtType = 1 + outerECHExt echExtType = 0 +) + +func parseECHExt(ext []byte) (echType echExtType, cs echCipher, configID uint8, encap []byte, payload []byte, err error) { + data := make([]byte, len(ext)) + copy(data, ext) + s := cryptobyte.String(data) + var echInt uint8 + if !s.ReadUint8(&echInt) { + err = errMalformedECHExt + return + } + echType = echExtType(echInt) + if echType == innerECHExt { + if !s.Empty() { + err = errMalformedECHExt + return + } + return echType, cs, 0, nil, nil, nil + } + if echType != outerECHExt { + err = errInvalidECHExt + return + } + if !s.ReadUint16(&cs.KDFID) { + err = errMalformedECHExt + return + } + if !s.ReadUint16(&cs.AEADID) { + err = errMalformedECHExt + return + } + if !s.ReadUint8(&configID) { + err = errMalformedECHExt + return + } + if !readUint16LengthPrefixed(&s, &encap) { + err = errMalformedECHExt + return + } + if !readUint16LengthPrefixed(&s, &payload) { + err = errMalformedECHExt + return + } + + // NOTE: clone encap and payload so that mutating them does not mutate the + // raw extension bytes. + return echType, cs, configID, bytes.Clone(encap), bytes.Clone(payload), nil +} + +func marshalEncryptedClientHelloConfigList(configs []EncryptedClientHelloKey) ([]byte, error) { + builder := cryptobyte.NewBuilder(nil) + builder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) { + for _, c := range configs { + builder.AddBytes(c.Config) + } + }) + return builder.Bytes() +} + +func (c *Conn) processECHClientHello(outer *clientHelloMsg, echKeys []EncryptedClientHelloKey) (*clientHelloMsg, *echServerContext, error) { + echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello) + if err != nil { + if errors.Is(err, errInvalidECHExt) { + c.sendAlert(alertIllegalParameter) + } else { + c.sendAlert(alertDecodeError) + } + + return nil, nil, errInvalidECHExt + } + + if echType == innerECHExt { + return outer, &echServerContext{inner: true}, nil + } + + if len(echKeys) == 0 { + return outer, nil, nil + } + + for _, echKey := range echKeys { + skip, config, err := parseECHConfig(echKey.Config) + if err != nil || skip { + c.sendAlert(alertInternalError) + return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKeys Config: %s", err) + } + if skip { + continue + } + echPriv, err := hpke.ParseHPKEPrivateKey(config.KemID, echKey.PrivateKey) + if err != nil { + c.sendAlert(alertInternalError) + return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKeys PrivateKey: %s", err) + } + info := append([]byte("tls ech\x00"), echKey.Config...) + hpkeContext, err := hpke.SetupRecipient(hpke.DHKEM_X25519_HKDF_SHA256, echCiphersuite.KDFID, echCiphersuite.AEADID, echPriv, info, encap) + if err != nil { + // attempt next trial decryption + continue + } + + encodedInner, err := decryptECHPayload(hpkeContext, outer.original, payload) + if err != nil { + // attempt next trial decryption + continue + } + + // NOTE: we do not enforce that the sent server_name matches the ECH + // configs PublicName, since this is not particularly important, and + // the client already had to know what it was in order to properly + // encrypt the payload. This is only a MAY in the spec, so we're not + // doing anything revolutionary. + + echInner, err := decodeInnerClientHello(outer, encodedInner) + if err != nil { + c.sendAlert(alertIllegalParameter) + return nil, nil, errInvalidECHExt + } + + c.echAccepted = true + + return echInner, &echServerContext{ + hpkeContext: hpkeContext, + configID: configID, + ciphersuite: echCiphersuite, + }, nil + } + + return outer, nil, nil +} + +func buildRetryConfigList(keys []EncryptedClientHelloKey) ([]byte, error) { + var atLeastOneRetryConfig bool + var retryBuilder cryptobyte.Builder + retryBuilder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, c := range keys { + if !c.SendAsRetry { + continue + } + atLeastOneRetryConfig = true + b.AddBytes(c.Config) + } + }) + if !atLeastOneRetryConfig { + return nil, nil + } + return retryBuilder.Bytes() +} diff --git a/crypto/tls/fips140_test.go b/crypto/tls/fips140_test.go new file mode 100644 index 00000000000..4efc3aaa129 --- /dev/null +++ b/crypto/tls/fips140_test.go @@ -0,0 +1,713 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto/rand" + "encoding/pem" + "fmt" + "math/big" + "net" + "os" + "runtime" + "strings" + "testing" + "time" + + "github.com/runZeroInc/excrypto/crypto/ecdsa" + "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/internal/boring" + "github.com/runZeroInc/excrypto/crypto/rsa" + "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/crypto/x509/pkix" + "github.com/runZeroInc/excrypto/internal/obscuretestdata" + "github.com/runZeroInc/excrypto/internal/testenv" +) + +func allCipherSuitesIncludingTLS13() []uint16 { + s := allCipherSuites() + for _, suite := range cipherSuitesTLS13 { + s = append(s, suite.id) + } + return s +} + +func isTLS13CipherSuite(id uint16) bool { + for _, suite := range cipherSuitesTLS13 { + if id == suite.id { + return true + } + } + return false +} + +func generateKeyShare(group CurveID) keyShare { + key, err := generateECDHEKey(rand.Reader, group) + if err != nil { + panic(err) + } + return keyShare{group: group, data: key.PublicKey().Bytes()} +} + +func TestFIPSServerProtocolVersion(t *testing.T) { + test := func(t *testing.T, name string, v uint16, msg string) { + t.Run(name, func(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.MinVersion = VersionSSL30 + clientConfig := testConfig.Clone() + clientConfig.MinVersion = v + clientConfig.MaxVersion = v + _, _, err := testHandshake(t, clientConfig, serverConfig) + if msg == "" { + if err != nil { + t.Fatalf("got error: %v, expected success", err) + } + } else { + if err == nil { + t.Fatalf("got success, expected error") + } + if !strings.Contains(err.Error(), msg) { + t.Fatalf("got error %v, expected %q", err, msg) + } + } + }) + } + + runWithFIPSDisabled(t, func(t *testing.T) { + test(t, "VersionTLS10", VersionTLS10, "") + test(t, "VersionTLS11", VersionTLS11, "") + test(t, "VersionTLS12", VersionTLS12, "") + test(t, "VersionTLS13", VersionTLS13, "") + }) + + runWithFIPSEnabled(t, func(t *testing.T) { + test(t, "VersionTLS10", VersionTLS10, "supported versions") + test(t, "VersionTLS11", VersionTLS11, "supported versions") + test(t, "VersionTLS12", VersionTLS12, "") + test(t, "VersionTLS13", VersionTLS13, "") + }) +} + +func isFIPSVersion(v uint16) bool { + return v == VersionTLS12 || v == VersionTLS13 +} + +func isFIPSCipherSuite(id uint16) bool { + name := CipherSuiteName(id) + if isTLS13CipherSuite(id) { + switch id { + case TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384: + return true + case TLS_CHACHA20_POLY1305_SHA256: + return false + default: + panic("unknown TLS 1.3 cipher suite: " + name) + } + } + switch id { + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return true + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + // Only for the native module. + return !boring.Enabled + } + switch { + case strings.Contains(name, "CHACHA20"): + return false + case strings.HasSuffix(name, "_SHA"): // SHA-1 + return false + case strings.HasPrefix(name, "TLS_RSA"): // RSA kex + return false + default: + panic("unknown cipher suite: " + name) + } +} + +func isFIPSCurve(id CurveID) bool { + switch id { + case CurveP256, CurveP384, CurveP521: + return true + case X25519MLKEM768: + // Only for the native module. + return !boring.Enabled + case X25519: + return false + default: + panic("unknown curve: " + id.String()) + } +} + +func isECDSA(id uint16) bool { + for _, suite := range cipherSuites { + if suite.id == id { + return suite.flags&suiteECSign == suiteECSign + } + } + return false // TLS 1.3 cipher suites are not tied to the signature algorithm. +} + +func isFIPSSignatureScheme(alg SignatureScheme) bool { + switch alg { + case PKCS1WithSHA256, + ECDSAWithP256AndSHA256, + PKCS1WithSHA384, + ECDSAWithP384AndSHA384, + PKCS1WithSHA512, + ECDSAWithP521AndSHA512, + PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512: + return true + case Ed25519: + // Only for the native module. + return !boring.Enabled + case PKCS1WithSHA1, ECDSAWithSHA1: + return false + default: + panic("unknown signature scheme: " + alg.String()) + } +} + +func TestFIPSServerCipherSuites(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.Certificates = make([]Certificate, 1) + + for _, id := range allCipherSuitesIncludingTLS13() { + if isECDSA(id) { + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + } else { + serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} + serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey + } + serverConfig.BuildNameToCertificate() + t.Run(fmt.Sprintf("suite=%s", CipherSuiteName(id)), func(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuites: []uint16{id}, + compressionMethods: []uint8{compressionNone}, + supportedCurves: defaultCurvePreferences(), + keyShares: []keyShare{generateKeyShare(CurveP256)}, + supportedPoints: []uint8{pointFormatUncompressed}, + supportedVersions: []uint16{VersionTLS12}, + supportedSignatureAlgorithms: allowedSignatureAlgorithmsFIPS, + } + if isTLS13CipherSuite(id) { + clientHello.supportedVersions = []uint16{VersionTLS13} + } + + runWithFIPSDisabled(t, func(t *testing.T) { + testClientHello(t, serverConfig, clientHello) + }) + + runWithFIPSEnabled(t, func(t *testing.T) { + msg := "" + if !isFIPSCipherSuite(id) { + msg = "no cipher suite supported by both client and server" + } + testClientHelloFailure(t, serverConfig, clientHello, msg) + }) + }) + } +} + +func TestFIPSServerCurves(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.CurvePreferences = nil + serverConfig.BuildNameToCertificate() + + for _, curveid := range defaultCurvePreferences() { + t.Run(fmt.Sprintf("curve=%v", curveid), func(t *testing.T) { + clientConfig := testConfig.Clone() + clientConfig.CurvePreferences = []CurveID{curveid} + + runWithFIPSDisabled(t, func(t *testing.T) { + if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil { + t.Fatalf("got error: %v, expected success", err) + } + }) + + // With fipstls forced, bad curves should be rejected. + runWithFIPSEnabled(t, func(t *testing.T) { + _, _, err := testHandshake(t, clientConfig, serverConfig) + if err != nil && isFIPSCurve(curveid) { + t.Fatalf("got error: %v, expected success", err) + } else if err == nil && !isFIPSCurve(curveid) { + t.Fatalf("got success, expected error") + } + }) + }) + } +} + +func fipsHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) { + c, s := localPipe(t) + client := Client(c, clientConfig) + server := Server(s, serverConfig) + done := make(chan error, 1) + go func() { + done <- client.Handshake() + c.Close() + }() + serverErr = server.Handshake() + s.Close() + clientErr = <-done + return +} + +func TestFIPSServerSignatureAndHash(t *testing.T) { + defer func() { + testingOnlySupportedSignatureAlgorithms = nil + }() + defer func(godebug string) { + os.Setenv("GODEBUG", godebug) + }(os.Getenv("GODEBUG")) + os.Setenv("GODEBUG", "tlssha1=1") + + for _, sigHash := range defaultSupportedSignatureAlgorithms() { + t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.Certificates = make([]Certificate, 1) + + testingOnlySupportedSignatureAlgorithms = []SignatureScheme{sigHash} + + sigType, _, _ := typeAndHashFromSignatureScheme(sigHash) + switch sigType { + case signaturePKCS1v15, signatureRSAPSS: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testRSAPSS2048Certificate} + serverConfig.Certificates[0].PrivateKey = testRSAPSS2048PrivateKey + case signatureEd25519: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testEd25519Certificate} + serverConfig.Certificates[0].PrivateKey = testEd25519PrivateKey + case signatureECDSA: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + } + serverConfig.BuildNameToCertificate() + // PKCS#1 v1.5 signature algorithms can't be used standalone in TLS + // 1.3, and the ECDSA ones bind to the curve used. + serverConfig.MaxVersion = VersionTLS12 + + runWithFIPSDisabled(t, func(t *testing.T) { + clientErr, serverErr := fipsHandshake(t, testConfig, serverConfig) + if clientErr != nil { + t.Fatalf("expected handshake with %v to succeed; client error: %v; server error: %v", sigHash, clientErr, serverErr) + } + }) + + // With fipstls forced, bad curves should be rejected. + runWithFIPSEnabled(t, func(t *testing.T) { + clientErr, _ := fipsHandshake(t, testConfig, serverConfig) + if isFIPSSignatureScheme(sigHash) { + if clientErr != nil { + t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr) + } + } else { + if clientErr == nil { + t.Fatalf("expected handshake with %v to fail, but it succeeded", sigHash) + } + } + }) + }) + } +} + +func TestFIPSClientHello(t *testing.T) { + runWithFIPSEnabled(t, testFIPSClientHello) +} + +func testFIPSClientHello(t *testing.T) { + // Test that no matter what we put in the client config, + // the client does not offer non-FIPS configurations. + + c, s := net.Pipe() + defer c.Close() + defer s.Close() + + clientConfig := testConfig.Clone() + // All sorts of traps for the client to avoid. + clientConfig.MinVersion = VersionSSL30 + clientConfig.MaxVersion = VersionTLS13 + clientConfig.CipherSuites = allCipherSuites() + clientConfig.CurvePreferences = defaultCurvePreferences() + + go Client(c, clientConfig).Handshake() + srv := Server(s, testConfig) + msg, err := srv.readHandshake(nil) + if err != nil { + t.Fatal(err) + } + hello, ok := msg.(*clientHelloMsg) + if !ok { + t.Fatalf("unexpected message type %T", msg) + } + + if !isFIPSVersion(hello.vers) { + t.Errorf("client vers=%#x", hello.vers) + } + for _, v := range hello.supportedVersions { + if !isFIPSVersion(v) { + t.Errorf("client offered disallowed version %#x", v) + } + } + for _, id := range hello.cipherSuites { + if !isFIPSCipherSuite(id) { + t.Errorf("client offered disallowed suite %v", CipherSuiteName(id)) + } + } + for _, id := range hello.supportedCurves { + if !isFIPSCurve(id) { + t.Errorf("client offered disallowed curve %v", id) + } + } + for _, sigHash := range hello.supportedSignatureAlgorithms { + if !isFIPSSignatureScheme(sigHash) { + t.Errorf("client offered disallowed signature-and-hash %v", sigHash) + } + } +} + +func TestFIPSCertAlgs(t *testing.T) { + // arm and wasm time out generating keys. Nothing in this test is + // architecture-specific, so just don't bother on those. + if testenv.CPUIsSlow() { + t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH) + } + + // Set up some roots, intermediate CAs, and leaf certs with various algorithms. + // X_Y is X signed by Y. + R1 := fipsCert(t, "R1", fipsRSAKey(t, 2048), nil, fipsCertCA|fipsCertFIPSOK) + R2 := fipsCert(t, "R2", fipsRSAKey(t, 1024), nil, fipsCertCA) + R3 := fipsCert(t, "R3", fipsRSAKey(t, 4096), nil, fipsCertCA|fipsCertFIPSOK) + + M1_R1 := fipsCert(t, "M1_R1", fipsECDSAKey(t, elliptic.P256()), R1, fipsCertCA|fipsCertFIPSOK) + M2_R1 := fipsCert(t, "M2_R1", fipsECDSAKey(t, elliptic.P224()), R1, fipsCertCA) + + I_R1 := fipsCert(t, "I_R1", fipsRSAKey(t, 3072), R1, fipsCertCA|fipsCertFIPSOK) + I_R2 := fipsCert(t, "I_R2", I_R1.key, R2, fipsCertCA|fipsCertFIPSOK) + I_M1 := fipsCert(t, "I_M1", I_R1.key, M1_R1, fipsCertCA|fipsCertFIPSOK) + I_M2 := fipsCert(t, "I_M2", I_R1.key, M2_R1, fipsCertCA|fipsCertFIPSOK) + + I_R3 := fipsCert(t, "I_R3", fipsRSAKey(t, 3072), R3, fipsCertCA|fipsCertFIPSOK) + fipsCert(t, "I_R3", I_R3.key, R3, fipsCertCA|fipsCertFIPSOK) + + L1_I := fipsCert(t, "L1_I", fipsECDSAKey(t, elliptic.P384()), I_R1, fipsCertLeaf|fipsCertFIPSOK) + L2_I := fipsCert(t, "L2_I", fipsRSAKey(t, 1024), I_R1, fipsCertLeaf) + + // client verifying server cert + testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { + clientConfig := testConfig.Clone() + clientConfig.RootCAs = pool + clientConfig.InsecureSkipVerify = false + clientConfig.ServerName = "example.com" + + serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} + serverConfig.BuildNameToCertificate() + + clientErr, _ := fipsHandshake(t, clientConfig, serverConfig) + + if (clientErr == nil) == ok { + if ok { + t.Logf("%s: accept", desc) + } else { + t.Logf("%s: reject", desc) + } + } else { + if ok { + t.Errorf("%s: BAD reject (%v)", desc, clientErr) + } else { + t.Errorf("%s: BAD accept", desc) + } + } + } + + // server verifying client cert + testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { + clientConfig := testConfig.Clone() + clientConfig.ServerName = "example.com" + clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} + + serverConfig := testConfig.Clone() + serverConfig.ClientCAs = pool + serverConfig.ClientAuth = RequireAndVerifyClientCert + + _, serverErr := fipsHandshake(t, clientConfig, serverConfig) + + if (serverErr == nil) == ok { + if ok { + t.Logf("%s: accept", desc) + } else { + t.Logf("%s: reject", desc) + } + } else { + if ok { + t.Errorf("%s: BAD reject (%v)", desc, serverErr) + } else { + t.Errorf("%s: BAD accept", desc) + } + } + } + + // Run simple basic test with known answers before proceeding to + // exhaustive test with computed answers. + r1pool := x509.NewCertPool() + r1pool.AddCert(R1.cert) + + runWithFIPSDisabled(t, func(t *testing.T) { + testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) + testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) + }) + + runWithFIPSEnabled(t, func(t *testing.T) { + testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) + testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) + }) + + if t.Failed() { + t.Fatal("basic test failed, skipping exhaustive test") + } + + if testing.Short() { + t.Logf("basic test passed; skipping exhaustive test in -short mode") + return + } + + for l := 1; l <= 2; l++ { + leaf := L1_I + if l == 2 { + leaf = L2_I + } + for i := 0; i < 64; i++ { + reachable := map[string]bool{leaf.parentOrg: true} + reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK} + list := [][]byte{leaf.der} + listName := leaf.name + addList := func(cond int, c *fipsCertificate) { + if cond != 0 { + list = append(list, c.der) + listName += "," + c.name + if reachable[c.org] { + reachable[c.parentOrg] = true + } + if reachableFIPS[c.org] && c.fipsOK { + reachableFIPS[c.parentOrg] = true + } + } + } + addList(i&1, I_R1) + addList(i&2, I_R2) + addList(i&4, I_M1) + addList(i&8, I_M2) + addList(i&16, M1_R1) + addList(i&32, M2_R1) + + for r := 1; r <= 3; r++ { + pool := x509.NewCertPool() + rootName := "," + shouldVerify := false + shouldVerifyFIPS := false + addRoot := func(cond int, c *fipsCertificate) { + if cond != 0 { + rootName += "," + c.name + pool.AddCert(c.cert) + if reachable[c.org] { + shouldVerify = true + } + if reachableFIPS[c.org] && c.fipsOK { + shouldVerifyFIPS = true + } + } + } + addRoot(r&1, R1) + addRoot(r&2, R2) + rootName = rootName[1:] // strip leading comma + + runWithFIPSDisabled(t, func(t *testing.T) { + testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify) + testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify) + }) + + runWithFIPSEnabled(t, func(t *testing.T) { + testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS) + testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS) + }) + } + } + } +} + +const ( + fipsCertCA = iota + fipsCertLeaf + fipsCertFIPSOK = 0x80 +) + +func fipsRSAKey(t *testing.T, size int) *rsa.PrivateKey { + k, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { + t.Fatal(err) + } + return k +} + +func fipsECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey { + k, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { + t.Fatal(err) + } + return k +} + +type fipsCertificate struct { + name string + org string + parentOrg string + der []byte + cert *x509.Certificate + key interface{} + fipsOK bool +} + +func fipsCert(t *testing.T, name string, key interface{}, parent *fipsCertificate, mode int) *fipsCertificate { + org := name + parentOrg := "" + if i := strings.Index(org, "_"); i >= 0 { + org = org[:i] + parentOrg = name[i+1:] + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + Organization: []string{org}, + }, + NotBefore: time.Unix(0, 0), + NotAfter: time.Unix(0, 0), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + if mode&^fipsCertFIPSOK == fipsCertLeaf { + tmpl.DNSNames = []string{"example.com"} + } else { + tmpl.IsCA = true + tmpl.KeyUsage |= x509.KeyUsageCertSign + } + + var pcert *x509.Certificate + var pkey interface{} + if parent != nil { + pcert = parent.cert + pkey = parent.key + } else { + pcert = tmpl + pkey = key + } + + var pub interface{} + var desc string + switch k := key.(type) { + case *rsa.PrivateKey: + pub = &k.PublicKey + desc = fmt.Sprintf("RSA-%d", k.N.BitLen()) + case *ecdsa.PrivateKey: + pub = &k.PublicKey + desc = "ECDSA-" + k.Curve.Params().Name + default: + t.Fatalf("invalid key %T", key) + } + + der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) + if err != nil { + t.Fatal(err) + } + cert, err := x509.ParseCertificate(der) + if err != nil { + t.Fatal(err) + } + + fipsOK := mode&fipsCertFIPSOK != 0 + runWithFIPSEnabled(t, func(t *testing.T) { + if isCertificateAllowedFIPS(cert) != fipsOK { + t.Errorf("fipsAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK) + } + }) + + return &fipsCertificate{name, org, parentOrg, der, cert, key, fipsOK} +} + +// A self-signed test certificate with an RSA key of size 2048, for testing +// RSA-PSS with SHA512. SAN of example.golang. +var ( + testRSAPSS2048Certificate []byte + testRSAPSS2048PrivateKey *rsa.PrivateKey +) + +func init() { + block, _ := pem.Decode(obscuretestdata.Rot13([]byte(` +-----ORTVA PREGVSVPNGR----- +ZVVP/mPPNrrtNjVONtVENYUUK/xu4+4mZH9QnemORpDjQDLWXbMVuipANDRYODNj +RwRDZN4TN1HRPuZUDJAgMFOQomNrSj0kZGNkZQRkAGN0ZQInSj0lZQRlZwxkAGN0 +ZQInZOVkRQNBOtAIONbGO0SwoJHtD28jttRvZN0TPFdTFVo3QDRONDHNN4VOQjNj +ttRXNbVONDPs8sx0A6vrPOK4VBIVsXvgg4xTpBDYrvzPsfwddUplfZVITRgSFZ6R +4Nl141s/7VdqJ0HgVdAo4CKuEBVQ7lQkE284kY6KoPhi/g5uC3HpruLp3uzYvlIq +ZxMDvMJgsHHWs/1dBgZ+buAt59YEJc4q+6vK0yn1WY3RjPVpxxAwW9uDoS7Co2PF ++RF9Lb55XNnc8XBoycpE8ZOFA38odajwsDqPKiBRBwnz2UHkXmRSK5ZN+sN0zr4P +vbPpPEYJXy+TbA9S8sNOsbM+G+2rny4QYhB95eKE8FeBVIOu3KSBe/EIuwgKpAIS +MXpiQg6q68I6wNXNLXz5ayw9TCcq4i+eNtZONNTwHQOBZN4TN1HqQjRO/jDRNjVS +bQNGOtAIUFHRQQNXOtteOtRSODpQNGNZOtAIUEZONs8RNwNNZOxTN1HqRDDFZOPP +QzI4LJ1joTHhM29fLJ5aZN0TPFdTFVo3QDROPjHNN4VONDPBbLfIpSPOuobdr3JU +qP6I7KKKRPzawu01e8u80li0AE379aFQ3pj2Z+UXinKlfJdey5uwTIXj0igjQ81e +I4WmQh7VsVbt5z8+DAP+7YdQMfm88iQXBefblFIBzHPtzPXSKrj+YN+rB/vDRWGe +7rafqqBrKWRc27Rq5iJ+xzJJ3Dztyp2Tjl8jSeZQVdaeaBmON4bPaQRtgKWg0mbt +aEjosRZNJv1nDEl5qG9XN3FC9zb5FrGSFmTTUvR4f4tUHr7wifNSS2dtgQ6+jU6f +m9o6fukaP7t5VyOXuV7FIO/Hdg2lqW+xU1LowZpVd6ANZ5rAZXtMhWe3+mjfFtju +TAnR +-----RAQ PREGVSVPNGR-----`))) + testRSAPSS2048Certificate = block.Bytes + + block, _ = pem.Decode(obscuretestdata.Rot13([]byte(` +-----ORTVA EFN CEVINGR XRL----- +ZVVRcNVONNXPNDRNa/U5AQrbattI+PQyFUlbeorWOaQxP3bcta7V6du3ZeQPSEuY +EHwBuBNZgrAK/+lXaIgSYFXwJ+Q14HGvN+8t8HqiBZF+y2jee/7rLG91UUbJUA4M +v4fyKGWTHVzIeK1SPK/9nweGCdVGLBsF0IdrUshby9WJgFF9kZNvUWWQLlsLHTkr +m29txiuRiJXBrFtTdsPwz5nKRsQNHwq/T6c8V30UDy7muQb2cgu1ZFfkOI+GNCaj +AWahNbdNaNxF1vcsudQsEsUjNK6Tsx/gazcrNl7wirn10sRdmvSDLq1kGd/0ILL7 +I3QIEJFaYj7rariSrbjPtTPchM5L/Ew6KrY/djVQNDNONbVONDPAcZMvsq/it42u +UqPiYhMnLF0E7FhaSycbKRfygTqYSfac0VsbWM/htSDOFNVVsYjZhzH6bKN1m7Hi +98nVLI61QrCeGPQIQSOfUoAzC8WNb8JgohfRojq5mlbO7YLT2+pyxWxyJR73XdHd +ezV+HWrlFpy2Tva7MGkOKm1JCOx9IjpajxrnKctNFVOJ23suRPZ9taLRRjnOrm5G +6Zr8q1gUgLDi7ifXr7eb9j9/UXeEKrwdLXX1YkxusSevlI+z8YMWMa2aKBn6T3tS +Ao8Dx1Hx5CHORAOzlZSWuG4Z/hhFd4LgZeeB2tv8D+sCuhTmp5FfuLXEOc0J4C5e +zgIPgRSENbTONZRAOVSYeI2+UfTw0kLSnfXbi/DCr6UFGE1Uu2VMBAc+bX4bfmJR +wOG4IpaVGzcy6gP1Jl4TpekwAtXVSMNw+1k1YHHYqbeKxhT8le0gNuT9mAlsJfFl +CeFbiP0HIome8Wkkyn+xDIkRDDdJDkCyRIhY8xKnVQN6Ylg1Uchn2YiCNbTONADM +p6Yd2G7+OkYkAqv2z8xMmrw5xtmOc/KqIfoSJEyroVK2XeSUfeUmG9CHx3QR1iMX +Z6cmGg94aDuJFxQtPnj1FbuRyW3USVSjphfS1FWNp3cDrcq8ht6VLqycQZYgOw/C +/5C6OIHgtb05R4+V/G3vLngztyDkGgyM0ExFI2yyNbTONYBKxXSK7nuCis0JxfQu +hGshSBGCbbjtDT0RctJ0jEqPkrt/WYvp3yFQ0tfggDI2JfErpelJpknryEt10EzB +38OobtzunS4kitfFihwBsvMGR8bX1G43Z+6AXfVyZY3LVYocH/9nWkCJl0f2QdQe +pDWuMeyx+cmwON7Oas/HEqjkNbTNXE/PAj14Q+zeY3LYoovPKvlqdkIjki5cqMqm +8guv3GApfJP4vTHEqpIdosHvaICqWvKr/Xnp3JTPrEWnSItoXNBkYgv1EO5ZxVut +Q8rlhcOdx4J1Y1txekdfqw4GSykxjZljwy2R2F4LlD8COg6I04QbIEMfVXmdm+CS +HvbaCd0PtLOPLKidvbWuCrjxBd/L5jeQOrMJ1SDX5DQ9J5Z8/5mkq4eqiWgwuoWc +bBegiZqey6hcl9Um4OWQ3SKjISvCSR7wdrAdv0S21ivYkOCZZQ3HBQS6YY5RlYvE +9I4kIZF8XKkit7ekfhdmZCfpIvnJHY6JAIOufQ2+92qUkFKmm5RWXD== +-----RAQ EFN CEVINGR XRL-----`))) + var err error + testRSAPSS2048PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + panic(err) + } +} diff --git a/crypto/tls/fipsonly/fipsonly.go b/crypto/tls/fipsonly/fipsonly.go new file mode 100644 index 00000000000..7e25c266438 --- /dev/null +++ b/crypto/tls/fipsonly/fipsonly.go @@ -0,0 +1,29 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +// Package fipsonly restricts all TLS configuration to FIPS-approved settings. +// +// The effect is triggered by importing the package anywhere in a program, as in: +// +// import _ "crypto/tls/fipsonly" +// +// This package only exists when using Go compiled with GOEXPERIMENT=boringcrypto. +package fipsonly + +// This functionality is provided as a side effect of an import to make +// it trivial to add to an existing program. It requires only a single line +// added to an existing source file, or it can be done by adding a whole +// new source file and not modifying any existing source files. + +import ( + "github.com/runZeroInc/excrypto/crypto/internal/boring/sig" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" +) + +func init() { + fips140tls.Force() + sig.FIPSOnly() +} diff --git a/crypto/tls/fipsonly/fipsonly_test.go b/crypto/tls/fipsonly/fipsonly_test.go new file mode 100644 index 00000000000..e25a0661eb7 --- /dev/null +++ b/crypto/tls/fipsonly/fipsonly_test.go @@ -0,0 +1,19 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build boringcrypto + +package fipsonly + +import ( + "testing" + + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" +) + +func Test(t *testing.T) { + if !fips140tls.Required() { + t.Fatal("fips140tls.Required() = false, must be true") + } +} diff --git a/crypto/tls/handshake_client.go b/crypto/tls/handshake_client.go index 22fb1673d38..6a7b772d651 100644 --- a/crypto/tls/handshake_client.go +++ b/crypto/tls/handshake_client.go @@ -10,22 +10,25 @@ import ( "encoding/binary" "errors" "fmt" - "hash" "io" "net" + "slices" "strconv" "strings" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/ed25519" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls13" "github.com/runZeroInc/excrypto/crypto/internal/hpke" - "github.com/runZeroInc/excrypto/crypto/internal/mlkem768" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/internal/byteorder" "github.com/runZeroInc/excrypto/internal/godebug" ) @@ -230,9 +233,7 @@ func (c *ClientFingerprintConfiguration) marshal(config *Config) ([]byte, error) return hello, nil } -var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme - -func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echContext, error) { +func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echClientContext, error) { config := c.config if len(config.ServerName) == 0 && !config.InsecureSkipVerify { return nil, nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") @@ -254,7 +255,10 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon if len(supportedVersions) == 0 { return nil, nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") } - maxVersion := config.maxSupportedVersion(roleClient) + // Since supportedVersions is sorted in descending order, the first element + // is the maximum version and the last element is the minimum version. + maxVersion := supportedVersions[0] + minVersion := supportedVersions[len(supportedVersions)-1] hello := &clientHelloMsg{ vers: maxVersion, @@ -282,24 +286,12 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon hello.secureRenegotiation = c.clientFinished[:] } - preferenceOrder := cipherSuitesPreferenceOrder - if !hasAESGCMHardwareSupport { - preferenceOrder = cipherSuitesPreferenceOrderNoAES - } - configCipherSuites := config.cipherSuites() - hello.cipherSuites = make([]uint16, 0, len(configCipherSuites)) - - for _, suiteId := range preferenceOrder { - suite := mutualCipherSuite(configCipherSuites, suiteId) - if suite == nil { - continue - } - // Don't advertise TLS 1.2-only cipher suites unless - // we're attempting TLS 1.2. - if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 { - continue - } - hello.cipherSuites = append(hello.cipherSuites, suiteId) + hello.cipherSuites = config.cipherSuites(hasAESGCMHardwareSupport) + // Don't advertise TLS 1.2-only cipher suites unless we're attempting TLS 1.2. + if maxVersion < VersionTLS12 { + hello.cipherSuites = slices.DeleteFunc(hello.cipherSuites, func(id uint16) bool { + return cipherSuiteByID(id).flags&suiteTLS12 != 0 + }) } _, err := io.ReadFull(config.rand(), hello.random) @@ -320,20 +312,19 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon } if maxVersion >= VersionTLS12 { - hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms() - } - if testingOnlyForceClientHelloSignatureAlgorithms != nil { - hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms + hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms(minVersion) + hello.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert() } var keyShareKeys *keySharePrivateKeys - if hello.supportedVersions[0] == VersionTLS13 { + if maxVersion >= VersionTLS13 { // Reset the list of ciphers when the client only supports TLS 1.3. - if len(hello.supportedVersions) == 1 { + if minVersion >= VersionTLS13 { hello.cipherSuites = nil } - if needFIPS() { - hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13FIPS...) + + if fips140tls.Required() { + hello.cipherSuites = append(hello.cipherSuites, allowedCipherSuitesTLS13FIPS...) } else if hasAESGCMHardwareSupport { hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) } else { @@ -345,27 +336,31 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon } curveID := hello.supportedCurves[0] keyShareKeys = &keySharePrivateKeys{curveID: curveID} - if curveID == x25519Kyber768Draft00 { + // Note that if X25519MLKEM768 is supported, it will be first because + // the preference order is fixed. + if curveID == X25519MLKEM768 { keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), X25519) if err != nil { return nil, nil, nil, err } - seed := make([]byte, mlkem768.SeedSize) + seed := make([]byte, mlkem.SeedSize) if _, err := io.ReadFull(config.rand(), seed); err != nil { return nil, nil, nil, err } - keyShareKeys.kyber, err = mlkem768.NewKeyFromSeed(seed) + keyShareKeys.mlkem, err = mlkem.NewDecapsulationKey768(seed) if err != nil { return nil, nil, nil, err } - // For draft-tls-westerbaan-xyber768d00-03, we send both a hybrid - // and a standard X25519 key share, since most servers will only - // support the latter. We reuse the same X25519 ephemeral key for - // both, as allowed by draft-ietf-tls-hybrid-design-09, Section 3.2. + mlkemEncapsulationKey := keyShareKeys.mlkem.EncapsulationKey().Bytes() + x25519EphemeralKey := keyShareKeys.ecdhe.PublicKey().Bytes() hello.keyShares = []keyShare{ - {group: x25519Kyber768Draft00, data: append(keyShareKeys.ecdhe.PublicKey().Bytes(), - keyShareKeys.kyber.EncapsulationKey()...)}, - {group: X25519, data: keyShareKeys.ecdhe.PublicKey().Bytes()}, + {group: X25519MLKEM768, data: append(mlkemEncapsulationKey, x25519EphemeralKey...)}, + } + // If both X25519MLKEM768 and X25519 are supported, we send both key + // shares (as a fallback) and we reuse the same X25519 ephemeral + // key, as allowed by draft-ietf-tls-hybrid-design-09, Section 3.2. + if slices.Contains(hello.supportedCurves, X25519) { + hello.keyShares = append(hello.keyShares, keyShare{group: X25519, data: x25519EphemeralKey}) } } else { if _, ok := curveForCurveID(curveID); !ok { @@ -390,7 +385,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon hello.quicTransportParameters = p } - var ech *echContext + var ech *echClientContext if c.config.EncryptedClientHelloConfigList != nil { if c.config.MinVersion != 0 && c.config.MinVersion < VersionTLS13 { return nil, nil, nil, errors.New("tls: MinVersion must be >= VersionTLS13 if EncryptedClientHelloConfigList is populated") @@ -406,7 +401,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon if echConfig == nil { return nil, nil, nil, errors.New("tls: EncryptedClientHelloConfigList contains no valid configs") } - ech = &echContext{config: echConfig} + ech = &echClientContext{config: echConfig} hello.encryptedClientHello = []byte{1} // indicate inner hello // We need to explicitly set these 1.2 fields to nil, as we do not // marshal them when encoding the inner hello, otherwise transcripts @@ -435,7 +430,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon return hello, keyShareKeys, ech, nil } -type echContext struct { +type echClientContext struct { config *echConfig hpkeContext *hpke.Sender encapsulatedKey []byte @@ -444,6 +439,7 @@ type echContext struct { kdfID uint16 aeadID uint16 echRejected bool + retryConfigs []byte } func (c *Conn) clientHandshake(ctx context.Context) (err error) { @@ -454,6 +450,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { // This may be a renegotiation handshake, in which case some fields // need to be reset. c.didResume = false + c.curveID = 0 hello, keyShareKeys, ech, err := c.makeClientHello() if err != nil { @@ -519,7 +516,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { if err := transcriptMsg(hello, transcript); err != nil { return err } - earlyTrafficSecret := suite.deriveSecret(earlySecret, clientEarlyTrafficLabel, transcript) + earlyTrafficSecret := earlySecret.ClientEarlyTrafficSecret(transcript) c.quicSetWriteSecret(QUICEncryptionLevelEarly, suite.id, earlyTrafficSecret) } @@ -570,7 +567,6 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { binderKey: binderKey, echContext: ech, } - /// Continue handshakelog return hs.handshake() } @@ -581,12 +577,11 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { hello: hello, session: session, } - /// Continue handshakelog return hs.handshake() } func (c *Conn) loadSession(hello *clientHelloMsg) ( - session *SessionState, earlySecret, binderKey []byte, err error) { + session *SessionState, earlySecret *tls13.EarlySecret, binderKey []byte, err error) { if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { return nil, nil, nil, nil } @@ -658,6 +653,11 @@ func (c *Conn) loadSession(hello *clientHelloMsg) ( return nil, nil, nil, nil } + // FIPS 140-3 requires the use of Extended Master Secret. + if !session.extMasterSecret && fips140tls.Required() { + return nil, nil, nil, nil + } + hello.sessionTicket = session.ticket return } @@ -713,8 +713,8 @@ func (c *Conn) loadSession(hello *clientHelloMsg) ( hello.pskBinders = [][]byte{make([]byte, cipherSuite.hash.Size())} // Compute the PSK binders. See RFC 8446, Section 4.2.11.2. - earlySecret = cipherSuite.extract(session.secret, nil) - binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil) + earlySecret = tls13.NewEarlySecret(cipherSuite.hash.New, session.secret) + binderKey = earlySecret.ResumptionBinderKey() transcript := cipherSuite.hash.New() if err := computeAndUpdatePSK(hello, binderKey, transcript, cipherSuite.finishedHash); err != nil { return nil, nil, nil, err @@ -748,6 +748,19 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { func (hs *clientHandshakeState) handshake() error { c := hs.c + // If we did not load a session (hs.session == nil), but we did set a + // session ID in the transmitted client hello (hs.hello.sessionId != nil), + // it means we tried to negotiate TLS 1.3 and sent a random session ID as a + // compatibility measure (see RFC 8446, Section 4.1.2). + // + // Since we're now handshaking for TLS 1.2, if the server echoed the + // transmitted ID back to us, we know mischief is afoot: the session ID + // was random and can't possibly be recognized by the server. + if hs.session == nil && hs.hello.sessionId != nil && bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server echoed TLS 1.3 compatibility session ID in TLS 1.2") + } + isResume, err := hs.processServerHello() if err != nil { return err @@ -845,11 +858,11 @@ func (hs *clientHandshakeState) pickCipherSuite() error { return errors.New("tls: server chose an unconfigured cipher suite") } - if hs.c.config.CipherSuites == nil && !needFIPS() && rsaKexCiphers[hs.suite.id] { + if hs.c.config.CipherSuites == nil && !fips140tls.Required() && rsaKexCiphers[hs.suite.id] { tlsrsakex.Value() // ensure godebug is initialized tlsrsakex.IncNonDefault() } - if hs.c.config.CipherSuites == nil && !needFIPS() && tdesCiphers[hs.suite.id] { + if hs.c.config.CipherSuites == nil && !fips140tls.Required() && tdesCiphers[hs.suite.id] { tls3des.Value() // ensure godebug is initialized tls3des.IncNonDefault() } @@ -932,11 +945,12 @@ func (hs *clientHandshakeState) doFullHandshake() error { err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) c.handshakeLog.ServerKeyExchange = skx.MakeLog(keyAgreement) if err != nil { - c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertIllegalParameter) return err } - if len(skx.key) >= 3 && skx.key[0] == 3 /* named curve */ { - c.curveID = CurveID(byteorder.BeUint16(skx.key[1:])) + if keyAgreement, ok := keyAgreement.(*ecdheKeyAgreement); ok { + c.curveID = keyAgreement.curveID + c.peerSigAlg = keyAgreement.signatureAlgorithm } msg, err = c.readHandshake(&hs.finishedHash) @@ -950,20 +964,6 @@ func (hs *clientHandshakeState) doFullHandshake() error { certReq, ok := msg.(*certificateRequestMsg) if ok { certRequested = true - c.ClientCertificateRequested = true - c.ClientCertificateRequest = &ClientCertificateRequest{ - Raw: make([]byte, len(certReq.raw)), - HasSignatureAndHash: certReq.hasSignatureAlgorithm, - CertificateTypes: make([]byte, len(certReq.certificateTypes)), - SignatureAndHashes: make([]SigAndHash, len(certReq.supportedSignatureAlgorithms)), - CertificateAuthorities: make([][]byte, len(certReq.certificateAuthorities)), - } - copy(c.ClientCertificateRequest.Raw, certReq.raw) - copy(c.ClientCertificateRequest.CertificateTypes, certReq.certificateTypes) - copy(c.ClientCertificateRequest.CertificateAuthorities, certReq.certificateAuthorities) - for i, sh := range certReq.supportedSignatureAlgorithms { - c.ClientCertificateRequest.SignatureAndHashes[i] = SigAndHash{Signature: uint8(sh >> 8), Hash: uint8(0xff & sh)} - } cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) if chainToSend, err = c.getClientCertificate(cri); err != nil { @@ -1008,33 +1008,17 @@ func (hs *clientHandshakeState) doFullHandshake() error { } } - var cr, sr []byte - if hs.hello.extendedRandomEnabled { - helloRandomLen := len(hs.hello.random) - helloExtendedRandomLen := len(hs.hello.extendedRandom) - - cr = make([]byte, helloRandomLen+helloExtendedRandomLen) - copy(cr, hs.hello.random) - copy(cr[helloRandomLen:], hs.hello.extendedRandom) - } - - if hs.serverHello.extendedRandomEnabled { - serverRandomLen := len(hs.serverHello.random) - serverExtendedRandomLen := len(hs.serverHello.extendedRandom) - - sr = make([]byte, serverRandomLen+serverExtendedRandomLen) - copy(sr, hs.serverHello.random) - copy(sr[serverRandomLen:], hs.serverHello.extendedRandom) - } - - hs.preMasterSecret = make([]byte, len(preMasterSecret)) - copy(hs.preMasterSecret, preMasterSecret) - if hs.serverHello.extendedMasterSecret { c.extMasterSecret = true - hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash.Sum()) + hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, + hs.finishedHash.Sum()) } else { - hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) + if fips140tls.Required() { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: FIPS 140-3 requires the use of Extended Master Secret") + } + hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, + hs.hello.random, hs.serverHello.random) } if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil { c.sendAlert(alertInternalError) @@ -1055,7 +1039,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { if c.vers >= VersionTLS12 { signatureAlgorithm, err := selectSignatureScheme(c.vers, chainToSend, certReq.supportedSignatureAlgorithms) if err != nil { - c.sendAlert(alertIllegalParameter) + c.sendAlert(alertHandshakeFailure) return err } sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) @@ -1064,6 +1048,10 @@ func (hs *clientHandshakeState) doFullHandshake() error { } certVerify.hasSignatureAlgorithm = true certVerify.signatureAlgorithm = signatureAlgorithm + if sigHash == crypto.SHA1 { + tlssha1.Value() // ensure godebug is initialized + tlssha1.IncNonDefault() + } } else { sigType, sigHash, err = legacyTypeAndHashFromPublicKey(key.Public()) if err != nil { @@ -1130,10 +1118,23 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { } if hs.serverHello.compressionMethod != compressionNone { - c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertIllegalParameter) return false, errors.New("tls: server selected unsupported compression format") } + supportsPointFormat := false + offeredNonCompressedFormat := false + for _, format := range hs.serverHello.supportedPoints { + if format == pointFormatUncompressed { + supportsPointFormat = true + } else { + offeredNonCompressedFormat = true + } + } + if !supportsPointFormat && offeredNonCompressedFormat { + return false, errors.New("tls: server offered only incompatible point formats") + } + if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { c.secureRenegotiation = true if len(hs.serverHello.secureRenegotiation) != 0 { @@ -1184,20 +1185,20 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { hs.masterSecret = hs.session.secret c.extMasterSecret = hs.session.extMasterSecret c.peerCertificates = hs.session.peerCertificates - c.activeCertHandles = hs.c.activeCertHandles c.verifiedChains = hs.session.verifiedChains c.ocspResponse = hs.session.ocspResponse // Let the ServerHello SCTs override the session SCTs from the original - // connection, if any are provided + // connection, if any are provided. if len(c.scts) == 0 && len(hs.session.scts) != 0 { c.scts = hs.session.scts } + c.curveID = hs.session.curveID return true, nil } // checkALPN ensure that the server's choice of ALPN protocol is compatible with -// the protocols that we advertised in the Client Hello. +// the protocols that we advertised in the ClientHello. func checkALPN(clientProtos []string, serverProto string, quic bool) error { if serverProto == "" { if quic && len(clientProtos) > 0 { @@ -1314,7 +1315,6 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error { copy(out, finished.verifyData) c.handshakeLog.ClientFinished = finished.MakeLog() - return nil } @@ -1339,23 +1339,21 @@ func checkKeySize(n int) (max int, ok bool) { // verifyServerCertificate parses and verifies the provided chain, setting // c.verifiedChains and c.peerCertificates or sending the appropriate alert. func (c *Conn) verifyServerCertificate(certificates [][]byte) error { - activeHandles := make([]*activeCert, len(certificates)) certs := make([]*x509.Certificate, len(certificates)) for i, asn1Data := range certificates { cert, err := globalCertCache.newCert(asn1Data) if err != nil { - c.sendAlert(alertBadCertificate) + c.sendAlert(alertDecodeError) return errors.New("tls: failed to parse certificate from server: " + err.Error()) } - if cert.cert.PublicKeyAlgorithm == x509.RSA { - n := cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen() + if cert.PublicKeyAlgorithm == x509.RSA { + n := cert.PublicKey.(*rsa.PublicKey).N.BitLen() if max, ok := checkKeySize(n); !ok { c.sendAlert(alertBadCertificate) return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", max) } } - activeHandles[i] = cert - certs[i] = cert.cert + certs[i] = cert } echRejected := c.config.EncryptedClientHelloConfigList != nil && !c.echAccepted @@ -1376,21 +1374,18 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { for _, cert := range certs[1:] { opts.Intermediates.AddCert(cert) } - - var res []x509.CertificateChain - var err error - var validation *x509.Validation - res, validation, err = certs[0].ValidateWithStupidDetail(opts) - c.handshakeLog.ServerCertificates.addParsed(certs, validation) - + chains, expired, never, err := certs[0].Verify(opts) if err != nil { c.sendAlert(alertBadCertificate) return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} } - c.verifiedChains = make([][]*x509.Certificate, len(res)) - for i, cert := range res { - c.verifiedChains[i] = []*x509.Certificate(cert) + chains = append(chains, expired...) + chains = append(chains, never...) + c.verifiedChains, err = fipsAllowedChains(chains) + if err != nil { + c.sendAlert(alertBadCertificate) + return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} } } } else if !c.config.InsecureSkipVerify { @@ -1404,20 +1399,18 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { for _, cert := range certs[1:] { opts.Intermediates.AddCert(cert) } - var res []x509.CertificateChain - var err error - var validation *x509.Validation - res, validation, err = certs[0].ValidateWithStupidDetail(opts) - c.handshakeLog.ServerCertificates.addParsed(certs, validation) - + chains, expired, never, err := certs[0].Verify(opts) if err != nil { c.sendAlert(alertBadCertificate) return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} } - c.verifiedChains = make([][]*x509.Certificate, len(res)) - for i, cert := range res { - c.verifiedChains[i] = []*x509.Certificate(cert) + chains = append(chains, expired...) + chains = append(chains, never...) + c.verifiedChains, err = fipsAllowedChains(chains) + if err != nil { + c.sendAlert(alertBadCertificate) + return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} } } @@ -1429,7 +1422,6 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) } - c.activeCertHandles = activeHandles c.peerCertificates = certs if c.config.VerifyPeerCertificate != nil && !echRejected { diff --git a/crypto/tls/handshake_client_test.go b/crypto/tls/handshake_client_test.go index 619a4f8a1c8..f2fd64dacf7 100644 --- a/crypto/tls/handshake_client_test.go +++ b/crypto/tls/handshake_client_test.go @@ -30,6 +30,7 @@ import ( "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/crypto/rsa" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" "github.com/runZeroInc/excrypto/crypto/x509/pkix" "github.com/runZeroInc/excrypto/internal/byteorder" @@ -209,7 +210,7 @@ func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, var serverInfo bytes.Buffer for _, ext := range test.extensions { pem.Encode(&serverInfo, &pem.Block{ - Type: fmt.Sprintf("SERVERINFO FOR EXTENSION %d", byteorder.BeUint16(ext)), + Type: fmt.Sprintf("SERVERINFO FOR EXTENSION %d", byteorder.BEUint16(ext)), Bytes: ext, }) } @@ -435,7 +436,7 @@ func (test *clientTest) run(t *testing.T, write bool) { } if write { - clientConn.Close() + client.Close() path := test.dataPath() out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { @@ -850,13 +851,17 @@ func testResumption(t *testing.T, version uint16) { if testing.Short() { t.Skip("skipping in -short mode") } + + // Note: using RSA 2048 test certificates because they are compatible with FIPS mode. + testCertificates := []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} serverConfig := &Config{ MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, + Time: testTime, } - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) if err != nil { panic(err) } @@ -866,10 +871,11 @@ func testResumption(t *testing.T, version uint16) { clientConfig := &Config{ MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, ClientSessionCache: NewLRUClientSessionCache(32), RootCAs: rootCAs, ServerName: "example.golang", + Time: testTime, } testResumeState := func(test string, didResume bool) { @@ -916,7 +922,7 @@ func testResumption(t *testing.T, version uint16) { // An old session ticket is replaced with a ticket encrypted with a fresh key. ticket = getTicket() - serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } + serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } testResumeState("ResumeWithOldTicket", true) if bytes.Equal(ticket, getTicket()) { t.Fatal("old first ticket matches the fresh one") @@ -924,13 +930,13 @@ func testResumption(t *testing.T, version uint16) { // Once the session master secret is expired, a full handshake should occur. ticket = getTicket() - serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } + serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) } testResumeState("ResumeWithExpiredTicket", false) if bytes.Equal(ticket, getTicket()) { t.Fatal("expired first ticket matches the fresh one") } - serverConfig.Time = func() time.Time { return time.Now() } // reset the time back + serverConfig.Time = testTime // reset the time back key1 := randomKey() serverConfig.SetSessionTicketKeys([][32]byte{key1}) @@ -947,11 +953,11 @@ func testResumption(t *testing.T, version uint16) { testResumeState("KeyChangeFinish", true) // Age the session ticket a bit, but not yet expired. - serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } + serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } testResumeState("OldSessionTicket", true) ticket = getTicket() // Expire the session ticket, which would force a full handshake. - serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } + serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) } testResumeState("ExpiredSessionTicket", false) if bytes.Equal(ticket, getTicket()) { t.Fatal("new ticket wasn't provided after old ticket expired") @@ -959,7 +965,7 @@ func testResumption(t *testing.T, version uint16) { // Age the session ticket a bit at a time, but don't expire it. d := 0 * time.Hour - serverConfig.Time = func() time.Time { return time.Now().Add(d) } + serverConfig.Time = func() time.Time { return testTime().Add(d) } deleteTicket() testResumeState("GetFreshSessionTicket", false) for i := 0; i < 13; i++ { @@ -970,7 +976,7 @@ func testResumption(t *testing.T, version uint16) { // handshake occurs for TLS 1.2. Resumption should still occur for // TLS 1.3 since the client should be using a fresh ticket sent over // by the server. - d += 12 * time.Hour + d += 12*time.Hour + time.Minute if version == VersionTLS13 { testResumeState("ExpiredSessionTicket", true) } else { @@ -984,8 +990,9 @@ func testResumption(t *testing.T, version uint16) { // before the serverConfig is used works. serverConfig = &Config{ MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, + Time: testTime, } serverConfig.SetSessionTicketKeys([][32]byte{key2}) @@ -994,7 +1001,7 @@ func testResumption(t *testing.T, version uint16) { // In TLS 1.3, cross-cipher suite resumption is allowed as long as the KDF // hash matches. Also, Config.CipherSuites does not apply to TLS 1.3. if version != VersionTLS13 { - clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA} + clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384} testResumeState("DifferentCipherSuite", false) testResumeState("DifferentCipherSuiteRecovers", true) } @@ -1010,7 +1017,8 @@ func testResumption(t *testing.T, version uint16) { // Use a different curve than the client to force a HelloRetryRequest. CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256}, MaxVersion: version, - Certificates: testConfig.Certificates, + Certificates: testCertificates, + Time: testTime, } testResumeState("InitialHandshake", false) testResumeState("WithHelloRetryRequest", true) @@ -1018,8 +1026,9 @@ func testResumption(t *testing.T, version uint16) { // Reset serverConfig back. serverConfig = &Config{ MaxVersion: version, - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, - Certificates: testConfig.Certificates, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, + Time: testTime, } } @@ -1274,7 +1283,7 @@ func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) { go func() { client := Client(c, &Config{ ServerName: "foo", - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, NextProtos: []string{"http", "something-else"}, }) errChan <- client.Handshake() @@ -1294,7 +1303,7 @@ func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) { serverHello := &serverHelloMsg{ vers: VersionTLS12, random: make([]byte, 32), - cipherSuite: TLS_RSA_WITH_AES_128_GCM_SHA256, + cipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, alpnProtocol: "how-about-this", } serverHelloBytes := mustMarshal(t, serverHello) @@ -1310,7 +1319,7 @@ func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) { s.Close() if err := <-errChan; !strings.Contains(err.Error(), "server selected unadvertised ALPN protocol") { - t.Fatalf("Expected error about unconfigured cipher suite but got %q", err) + t.Fatalf("Expected error about unconfigured ALPN protocol but got %q", err) } } @@ -1726,7 +1735,10 @@ func testVerifyConnection(t *testing.T, version uint16) { }, } for _, test := range tests { - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + // Note: using RSA 2048 test certificates because they are compatible with FIPS mode. + testCertificates := []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} + + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) if err != nil { panic(err) } @@ -1737,7 +1749,8 @@ func testVerifyConnection(t *testing.T, version uint16) { serverConfig := &Config{ MaxVersion: version, - Certificates: []Certificate{testConfig.Certificates[0]}, + Certificates: testCertificates, + Time: testTime, ClientCAs: rootCAs, NextProtos: []string{"protocol1"}, } @@ -1750,7 +1763,8 @@ func testVerifyConnection(t *testing.T, version uint16) { ClientSessionCache: NewLRUClientSessionCache(32), RootCAs: rootCAs, ServerName: "example.golang", - Certificates: []Certificate{testConfig.Certificates[0]}, + Certificates: testCertificates, + Time: testTime, NextProtos: []string{"protocol1"}, } test.configureClient(clientConfig, &clientCalled) @@ -1785,7 +1799,8 @@ func TestVerifyPeerCertificate(t *testing.T) { } func testVerifyPeerCertificate(t *testing.T, version uint16) { - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + // Note: using RSA 2048 test certificates because they are compatible with FIPS mode. + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) if err != nil { panic(err) } @@ -1793,8 +1808,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { rootCAs := x509.NewCertPool() rootCAs.AddCert(issuer) - now := func() time.Time { return time.Unix(1476984729, 0) } - sentinelErr := errors.New("TestVerifyPeerCertificate") verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { @@ -2040,11 +2053,11 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { config.ServerName = "example.golang" config.ClientAuth = RequireAndVerifyClientCert config.ClientCAs = rootCAs - config.Time = now + config.Time = testTime config.MaxVersion = version config.Certificates = make([]Certificate, 1) - config.Certificates[0].Certificate = [][]byte{testRSACertificate} - config.Certificates[0].PrivateKey = testRSAPrivateKey + config.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} + config.Certificates[0].PrivateKey = testRSA2048PrivateKey config.Certificates[0].SignedCertificateTimestamps = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} config.Certificates[0].OCSPStaple = []byte("dummy ocsp") test.configureServer(config, &serverCalled) @@ -2055,9 +2068,10 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { }() config := testConfig.Clone() + config.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} config.ServerName = "example.golang" config.RootCAs = rootCAs - config.Time = now + config.Time = testTime config.MaxVersion = version test.configureClient(config, &clientCalled) clientErr := Client(c, config).Handshake() @@ -2338,8 +2352,8 @@ var getClientCertificateTests = []struct { panic("empty AcceptableCAs") } cert := &Certificate{ - Certificate: [][]byte{testRSACertificate}, - PrivateKey: testRSAPrivateKey, + Certificate: [][]byte{testRSA2048Certificate}, + PrivateKey: testRSA2048PrivateKey, } return cert, nil } @@ -2359,25 +2373,34 @@ func TestGetClientCertificate(t *testing.T) { } func testGetClientCertificate(t *testing.T, version uint16) { - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + // Note: using RSA 2048 test certificates because they are compatible with FIPS mode. + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) if err != nil { panic(err) } for i, test := range getClientCertificateTests { serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} serverConfig.ClientAuth = VerifyClientCertIfGiven serverConfig.RootCAs = x509.NewCertPool() serverConfig.RootCAs.AddCert(issuer) serverConfig.ClientCAs = serverConfig.RootCAs - serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } + serverConfig.Time = testTime serverConfig.MaxVersion = version clientConfig := testConfig.Clone() + clientConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} clientConfig.MaxVersion = version test.setup(clientConfig, serverConfig) + // TLS 1.1 isn't available for FIPS required + if fips140tls.Required() && clientConfig.MaxVersion == VersionTLS11 { + t.Logf("skipping test %d for FIPS mode", i) + continue + } + type serverResult struct { cs ConnectionState err error @@ -2516,11 +2539,15 @@ func TestDowngradeCanary(t *testing.T) { if err := testDowngradeCanary(t, VersionTLS12, VersionTLS12); err != nil { t.Errorf("client didn't ignore expected TLS 1.2 canary") } - if err := testDowngradeCanary(t, VersionTLS11, VersionTLS11); err != nil { - t.Errorf("client unexpectedly reacted to a canary in TLS 1.1") - } - if err := testDowngradeCanary(t, VersionTLS10, VersionTLS10); err != nil { - t.Errorf("client unexpectedly reacted to a canary in TLS 1.0") + if !fips140tls.Required() { + if err := testDowngradeCanary(t, VersionTLS11, VersionTLS11); err != nil { + t.Errorf("client unexpectedly reacted to a canary in TLS 1.1") + } + if err := testDowngradeCanary(t, VersionTLS10, VersionTLS10); err != nil { + t.Errorf("client unexpectedly reacted to a canary in TLS 1.0") + } + } else { + t.Logf("skiping TLS 1.1 and TLS 1.0 downgrade canary checks in FIPS mode") } } @@ -2530,7 +2557,8 @@ func TestResumptionKeepsOCSPAndSCT(t *testing.T) { } func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { - issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + // Note: using RSA 2048 test certificates because they are compatible with FIPS mode. + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) if err != nil { t.Fatalf("failed to parse test issuer") } @@ -2541,8 +2569,10 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { ClientSessionCache: NewLRUClientSessionCache(32), ServerName: "example.golang", RootCAs: roots, + Time: testTime, } serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} serverConfig.MaxVersion = ver serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3} serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}} @@ -2627,8 +2657,8 @@ func TestClientHandshakeContextCancellation(t *testing.T) { if err != context.Canceled { t.Errorf("Unexpected client handshake error: %v", err) } - if runtime.GOARCH == "wasm" { - t.Skip("conn.Close does not error as expected when called multiple times on WASM") + if runtime.GOOS == "js" || runtime.GOOS == "wasip1" { + t.Skip("conn.Close does not error as expected when called multiple times on GOOS=js or GOOS=wasip1") } err = cli.Close() if err == nil { @@ -2677,11 +2707,15 @@ func testTLS13OnlyClientHelloCipherSuite(t *testing.T, ciphers []uint16) { serverConfig := &Config{ Certificates: testConfig.Certificates, GetConfigForClient: func(chi *ClientHelloInfo) (*Config, error) { - if len(chi.CipherSuites) != len(defaultCipherSuitesTLS13NoAES) { + expectedCiphersuites := defaultCipherSuitesTLS13NoAES + if fips140tls.Required() { + expectedCiphersuites = allowedCipherSuitesTLS13FIPS + } + if len(chi.CipherSuites) != len(expectedCiphersuites) { t.Errorf("only TLS 1.3 suites should be advertised, got=%x", chi.CipherSuites) } else { - for i := range defaultCipherSuitesTLS13NoAES { - if want, got := defaultCipherSuitesTLS13NoAES[i], chi.CipherSuites[i]; want != got { + for i := range expectedCiphersuites { + if want, got := expectedCiphersuites[i], chi.CipherSuites[i]; want != got { t.Errorf("cipher at index %d does not match, want=%x, got=%x", i, want, got) } } diff --git a/crypto/tls/handshake_client_tls13.go b/crypto/tls/handshake_client_tls13.go index 0d8a4d4a5fd..ed15fd380dc 100644 --- a/crypto/tls/handshake_client_tls13.go +++ b/crypto/tls/handshake_client_tls13.go @@ -8,13 +8,17 @@ import ( "bytes" "context" "errors" - "hash" "slices" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/crypto/hkdf" "github.com/runZeroInc/excrypto/crypto/hmac" - "github.com/runZeroInc/excrypto/crypto/internal/mlkem768" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls13" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/subtle" ) @@ -27,7 +31,7 @@ type clientHandshakeStateTLS13 struct { keyShareKeys *keySharePrivateKeys session *SessionState - earlySecret []byte + earlySecret *tls13.EarlySecret binderKey []byte certReq *certificateRequestMsgTLS13 @@ -35,10 +39,10 @@ type clientHandshakeStateTLS13 struct { sentDummyCCS bool suite *cipherSuiteTLS13 transcript hash.Hash - masterSecret []byte + masterSecret *tls13.MasterSecret trafficSecret []byte // client_application_traffic_secret_0 - echContext *echContext + echContext *echClientContext } // handshake requires hs.c, hs.hello, hs.serverHello, hs.keyShareKeys, and, @@ -84,18 +88,18 @@ func (hs *clientHandshakeStateTLS13) handshake() error { } } - var echRetryConfigList []byte if hs.echContext != nil { confTranscript := cloneHash(hs.echContext.innerTranscript, hs.suite.hash) confTranscript.Write(hs.serverHello.original[:30]) confTranscript.Write(make([]byte, 8)) confTranscript.Write(hs.serverHello.original[38:]) - acceptConfirmation := hs.suite.expandLabel( - hs.suite.extract(hs.echContext.innerHello.random, nil), - "ech accept confirmation", - confTranscript.Sum(nil), - 8, - ) + h := hs.suite.hash.New + prk, err := hkdf.Extract(h, hs.echContext.innerHello.random, nil) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + acceptConfirmation := tls13.ExpandLabel(h, prk, "ech accept confirmation", confTranscript.Sum(nil), 8) if subtle.ConstantTimeCompare(acceptConfirmation, hs.serverHello.random[len(hs.serverHello.random)-8:]) == 1 { hs.hello = hs.echContext.innerHello c.serverName = c.config.ServerName @@ -104,7 +108,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { if hs.serverHello.encryptedClientHello != nil { c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: unexpected encrypted_client_hello extension in server hello despite ECH being accepted") + return errors.New("tls: unexpected encrypted client hello extension in server hello despite ECH being accepted") } if hs.hello.serverName == "" && hs.serverHello.serverNameAck { @@ -113,9 +117,6 @@ func (hs *clientHandshakeStateTLS13) handshake() error { } } else { hs.echContext.echRejected = true - // If the server sent us retry configs, we'll return these to - // the user so they can update their Config. - echRetryConfigList = hs.serverHello.encryptedClientHello } } @@ -154,7 +155,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { if hs.echContext != nil && hs.echContext.echRejected { c.sendAlert(alertECHRequired) - return &ECHRejectionError{echRetryConfigList} + return &ECHRejectionError{hs.echContext.retryConfigs} } if hs.session != nil { @@ -208,8 +209,8 @@ func (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error { } if hs.serverHello.compressionMethod != compressionNone { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected unsupported compression format") + c.sendAlert(alertDecodeError) + return errors.New("tls: server sent non-zero legacy TLS compression method") } selectedSuite := mutualCipherSuiteTLS13(hs.hello.cipherSuites, hs.serverHello.cipherSuite) @@ -276,12 +277,13 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { copy(hrrHello, hs.serverHello.original) hrrHello = bytes.Replace(hrrHello, hs.serverHello.encryptedClientHello, make([]byte, 8), 1) confTranscript.Write(hrrHello) - acceptConfirmation := hs.suite.expandLabel( - hs.suite.extract(hs.echContext.innerHello.random, nil), - "hrr ech accept confirmation", - confTranscript.Sum(nil), - 8, - ) + h := hs.suite.hash.New + prk, err := hkdf.Extract(h, hs.echContext.innerHello.random, nil) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + acceptConfirmation := tls13.ExpandLabel(h, prk, "hrr ech accept confirmation", confTranscript.Sum(nil), 8) if subtle.ConstantTimeCompare(acceptConfirmation, hs.serverHello.encryptedClientHello) == 1 { hello = hs.echContext.innerHello c.serverName = c.config.ServerName @@ -296,7 +298,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { } else if hs.serverHello.encryptedClientHello != nil { // Unsolicited ECH extension should be rejected c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: unexpected ECH extension in serverHello") + return errors.New("tls: unexpected encrypted client hello extension in serverHello") } // The only HelloRetryRequest extensions we support are key_share and @@ -330,12 +332,11 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share") } - // Note: we don't support selecting X25519Kyber768Draft00 in a HRR, - // because we currently only support it at all when CurvePreferences is - // empty, which will cause us to also send a key share for it. + // Note: we don't support selecting X25519MLKEM768 in a HRR, because it + // is currently first in preference order, so if it's enabled we'll + // always send a key share for it. // - // This will have to change once we support selecting hybrid KEMs - // without sending key shares for them. + // This will have to change once we support multiple hybrid KEMs. if _, ok := curveForCurveID(curveID); !ok { c.sendAlert(alertInternalError) return errors.New("tls: CurvePreferences includes unsupported curve") @@ -477,7 +478,6 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { hs.usingPSK = true c.didResume = true c.peerCertificates = hs.session.peerCertificates - c.activeCertHandles = hs.session.activeCertHandles c.verifiedChains = hs.session.verifiedChains c.ocspResponse = hs.session.ocspResponse c.scts = hs.session.scts @@ -488,12 +488,12 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { c := hs.c ecdhePeerData := hs.serverHello.serverShare.data - if hs.serverHello.serverShare.group == x25519Kyber768Draft00 { - if len(ecdhePeerData) != x25519PublicKeySize+mlkem768.CiphertextSize { + if hs.serverHello.serverShare.group == X25519MLKEM768 { + if len(ecdhePeerData) != mlkem.CiphertextSize768+x25519PublicKeySize { c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid server key share") + return errors.New("tls: invalid server X25519MLKEM768 key share") } - ecdhePeerData = hs.serverHello.serverShare.data[:x25519PublicKeySize] + ecdhePeerData = hs.serverHello.serverShare.data[mlkem.CiphertextSize768:] } peerKey, err := hs.keyShareKeys.ecdhe.Curve().NewPublicKey(ecdhePeerData) if err != nil { @@ -505,33 +505,30 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: invalid server key share") } - if hs.serverHello.serverShare.group == x25519Kyber768Draft00 { - if hs.keyShareKeys.kyber == nil { + if hs.serverHello.serverShare.group == X25519MLKEM768 { + if hs.keyShareKeys.mlkem == nil { return c.sendAlert(alertInternalError) } - ciphertext := hs.serverHello.serverShare.data[x25519PublicKeySize:] - kyberShared, err := kyberDecapsulate(hs.keyShareKeys.kyber, ciphertext) + ciphertext := hs.serverHello.serverShare.data[:mlkem.CiphertextSize768] + mlkemShared, err := hs.keyShareKeys.mlkem.Decapsulate(ciphertext) if err != nil { c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid Kyber server key share") + return errors.New("tls: invalid X25519MLKEM768 server key share") } - sharedKey = append(sharedKey, kyberShared...) + sharedKey = append(mlkemShared, sharedKey...) } c.curveID = hs.serverHello.serverShare.group earlySecret := hs.earlySecret if !hs.usingPSK { - earlySecret = hs.suite.extract(nil, nil) + earlySecret = tls13.NewEarlySecret(hs.suite.hash.New, nil) } - handshakeSecret := hs.suite.extract(sharedKey, - hs.suite.deriveSecret(earlySecret, "derived", nil)) + handshakeSecret := earlySecret.HandshakeSecret(sharedKey) - clientSecret := hs.suite.deriveSecret(handshakeSecret, - clientHandshakeTrafficLabel, hs.transcript) + clientSecret := handshakeSecret.ClientHandshakeTrafficSecret(hs.transcript) c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret) - serverSecret := hs.suite.deriveSecret(handshakeSecret, - serverHandshakeTrafficLabel, hs.transcript) + serverSecret := handshakeSecret.ServerHandshakeTrafficSecret(hs.transcript) c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret) if c.quic != nil { @@ -553,8 +550,7 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { return err } - hs.masterSecret = hs.suite.extract(nil, - hs.suite.deriveSecret(handshakeSecret, "derived", nil)) + hs.masterSecret = handshakeSecret.MasterSecret() return nil } @@ -614,9 +610,13 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { return errors.New("tls: server accepted 0-RTT with the wrong ALPN") } } - if hs.echContext != nil && !hs.echContext.echRejected && encryptedExtensions.echRetryConfigs != nil { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server sent ECH retry configs after accepting ECH") + if hs.echContext != nil { + if hs.echContext.echRejected { + hs.echContext.retryConfigs = encryptedExtensions.echRetryConfigs + } else if encryptedExtensions.echRetryConfigs != nil { + c.sendAlert(alertUnsupportedExtension) + return errors.New("tls: server sent encrypted client hello retry configs after accepting encrypted client hello") + } } return nil @@ -714,7 +714,10 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { + // We don't use hs.hello.supportedSignatureAlgorithms because it might + // include PKCS#1 v1.5 and SHA-1 if the ClientHello also supported TLS 1.2. + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers)) || + !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, signatureSchemesForPublicKey(c.vers, c.peerCertificates[0].PublicKey)) { c.sendAlert(alertIllegalParameter) return errors.New("tls: certificate used with invalid signature algorithm") } @@ -723,8 +726,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { return c.sendAlert(alertInternalError) } if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: certificate used with invalid signature algorithm") + return c.sendAlert(alertInternalError) } signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, @@ -732,6 +734,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { c.sendAlert(alertDecryptError) return errors.New("tls: invalid signature by the server certificate: " + err.Error()) } + c.peerSigAlg = certVerify.signatureAlgorithm if err := transcriptMsg(certVerify, hs.transcript); err != nil { return err @@ -769,10 +772,8 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error { // Derive secrets that take context through the server Finished. - hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, - clientApplicationTrafficLabel, hs.transcript) - serverSecret := hs.suite.deriveSecret(hs.masterSecret, - serverApplicationTrafficLabel, hs.transcript) + hs.trafficSecret = hs.masterSecret.ClientApplicationTrafficSecret(hs.transcript) + serverSecret := hs.masterSecret.ServerApplicationTrafficSecret(hs.transcript) c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret) err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret) @@ -879,8 +880,7 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() error { c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret) if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil { - c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, - resumptionLabel, hs.transcript) + c.resumptionSecret = hs.masterSecret.ResumptionMasterSecret(hs.transcript) } if c.quic != nil { @@ -913,6 +913,11 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { return errors.New("tls: received a session ticket with invalid lifetime") } + if len(msg.label) == 0 { + c.sendAlert(alertDecodeError) + return errors.New("tls: received a session ticket with empty opaque ticket label") + } + // RFC 9001, Section 4.6.1 if c.quic != nil && msg.maxEarlyData != 0 && msg.maxEarlyData != 0xffffffff { c.sendAlert(alertIllegalParameter) @@ -924,11 +929,10 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { return c.sendAlert(alertInternalError) } - psk := cipherSuite.expandLabel(c.resumptionSecret, "resumption", + psk := tls13.ExpandLabel(cipherSuite.hash.New, c.resumptionSecret, "resumption", msg.nonce, cipherSuite.hash.Size()) session := c.sessionState() - session.lifetime = msg.lifetime session.secret = psk session.useBy = uint64(c.config.time().Add(lifetime).Unix()) session.ageAdd = msg.ageAdd diff --git a/crypto/tls/handshake_messages.go b/crypto/tls/handshake_messages.go index 236929d2c9c..b1eca8f6116 100644 --- a/crypto/tls/handshake_messages.go +++ b/crypto/tls/handshake_messages.go @@ -100,7 +100,7 @@ type clientHelloMsg struct { // extensions are only populated on the server-side of a handshake extensions []uint16 - // zcrypto + // excrypto heartbeatEnabled bool heartbeatMode uint8 extendedRandomEnabled bool @@ -317,11 +317,6 @@ func (m *clientHelloMsg) marshalMsg(echInner bool) ([]byte, error) { }) } } - if len(m.unknownExtensions) > 0 { - for _, unkExt := range m.unknownExtensions { - exts.AddBytes(unkExt) - } - } if len(m.keyShares) > 0 { // RFC 8446, Section 4.2.8 if echInner { @@ -729,6 +724,10 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { } m.pskBinders = append(m.pskBinders, binder) } + case extensionEncryptedClientHello: + if !extData.ReadBytes(&m.encryptedClientHello, len(extData)) { + return false + } default: buff := make([]byte, len(extData)) extData.CopyBytes(buff) @@ -777,7 +776,7 @@ func (m *clientHelloMsg) clone() *clientHelloMsg { pskBinders: slices.Clone(m.pskBinders), quicTransportParameters: slices.Clone(m.quicTransportParameters), encryptedClientHello: slices.Clone(m.encryptedClientHello), - // zcrypto + // excrypto heartbeatEnabled: m.heartbeatEnabled, heartbeatMode: m.heartbeatMode, extendedRandomEnabled: m.extendedRandomEnabled, @@ -812,7 +811,7 @@ type serverHelloMsg struct { cookie []byte selectedGroup CurveID - // zcrypto + // excrypto heartbeatEnabled bool heartbeatMode uint8 extendedRandomEnabled bool @@ -1115,6 +1114,7 @@ type encryptedExtensionsMsg struct { quicTransportParameters []byte earlyData bool echRetryConfigs []byte + serverNameAck bool } func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { @@ -1150,6 +1150,10 @@ func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { b.AddBytes(m.echRetryConfigs) }) } + if m.serverNameAck { + b.AddUint16(extensionServerName) + b.AddUint16(0) // empty extension_data + } }) }) @@ -1166,6 +1170,7 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -1174,6 +1179,11 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionALPN: var protoList cryptobyte.String @@ -1199,6 +1209,11 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { if !extData.CopyBytes(m.echRetryConfigs) { return false } + case extensionServerName: + if len(extData) != 0 { + return false + } + m.serverNameAck = true default: // Ignore unknown extensions. continue @@ -1908,7 +1923,7 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { } sigAndHashLen := uint16(data[0])<<8 | uint16(data[1]) data = data[2:] - if sigAndHashLen&1 != 0 { + if sigAndHashLen&1 != 0 || sigAndHashLen == 0 { return false } if len(data) < int(sigAndHashLen) { diff --git a/crypto/tls/handshake_messages_test.go b/crypto/tls/handshake_messages_test.go index 7166d6a0c32..279e2c3ca9b 100644 --- a/crypto/tls/handshake_messages_test.go +++ b/crypto/tls/handshake_messages_test.go @@ -73,10 +73,6 @@ func TestMarshalUnmarshal(t *testing.T) { break } - if m, ok := m.(*SessionState); ok { - m.activeCertHandles = nil - } - if ch, ok := m.(*clientHelloMsg); ok { // extensions is special cased, as it is only populated by the // server-side of a handshake and is not expected to roundtrip @@ -89,7 +85,7 @@ func TestMarshalUnmarshal(t *testing.T) { ch.extensions = nil } - // clientHelloMsg, serverHelloMsg, and clientKeyExchangeMsg, when unmarshalled, store + // clientHelloMsg and serverHelloMsg, when unmarshalled, store // their original representation, for later use in the handshake // transcript. In order to prevent DeepEqual from failing since // we didn't create the original message via unmarshalling, nil @@ -99,12 +95,6 @@ func TestMarshalUnmarshal(t *testing.T) { t.original = nil case *serverHelloMsg: t.original = nil - case *clientKeyExchangeMsg: - t.raw = nil - case *certificateRequestMsg: - t.raw = nil - case *certificateRequestMsgTLS13: - t.raw = nil } if !reflect.DeepEqual(m1, m) { @@ -190,10 +180,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { } } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12) } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms() + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12) } for i := 0; i < rand.Intn(5); i++ { m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand)) @@ -239,6 +229,9 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { if rand.Intn(10) > 5 { m.earlyData = true } + if rand.Intn(10) > 5 { + m.encryptedClientHello = randomBytes(rand.Intn(50)+1, rand) + } return reflect.ValueOf(m) } @@ -428,11 +421,13 @@ func (*SessionState) Generate(rand *rand.Rand, size int) reflect.Value { if rand.Intn(10) > 5 && s.EarlyData { s.alpnProtocol = string(randomBytes(rand.Intn(10), rand)) } - if s.isClient { - if isTLS13 { + if isTLS13 { + if s.isClient { s.useBy = uint64(rand.Int63()) s.ageAdd = uint32(rand.Int63() & math.MaxUint32) } + } else { + s.curveID = CurveID(rand.Intn(30000) + 1) } return reflect.ValueOf(s) } @@ -479,10 +474,10 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V m.scts = true } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS12) } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms() + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms(VersionTLS12) } if rand.Intn(10) > 5 { m.certificateAuthorities = make([][]byte, 3) diff --git a/crypto/tls/handshake_server.go b/crypto/tls/handshake_server.go index d8175c8ff2c..7ce639a9dee 100644 --- a/crypto/tls/handshake_server.go +++ b/crypto/tls/handshake_server.go @@ -8,17 +8,19 @@ import ( "context" "errors" "fmt" - "hash" "io" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/ed25519" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/subtle" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/internal/byteorder" ) // serverHandshakeState contains details of a server handshake in progress. @@ -42,7 +44,7 @@ type serverHandshakeState struct { // serverHandshake performs a TLS handshake as a server. func (c *Conn) serverHandshake(ctx context.Context) error { - clientHello, err := c.readClientHello(ctx) + clientHello, ech, err := c.readClientHello(ctx) if err != nil { return err } @@ -52,6 +54,7 @@ func (c *Conn) serverHandshake(ctx context.Context) error { c: c, ctx: ctx, clientHello: clientHello, + echContext: ech, } return hs.handshake() } @@ -132,17 +135,35 @@ func (hs *serverHandshakeState) handshake() error { } // readClientHello reads a ClientHello message and selects the protocol version. -func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { +func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, *echServerContext, error) { // clientHelloMsg is included in the transcript, but we haven't initialized // it yet. The respective handshake functions will record it themselves. msg, err := c.readHandshake(nil) if err != nil { - return nil, err + return nil, nil, err } clientHello, ok := msg.(*clientHelloMsg) if !ok { c.sendAlert(alertUnexpectedMessage) - return nil, unexpectedMessageError(clientHello, msg) + return nil, nil, unexpectedMessageError(clientHello, msg) + } + + // ECH processing has to be done before we do any other negotiation based on + // the contents of the client hello, since we may swap it out completely. + var ech *echServerContext + if len(clientHello.encryptedClientHello) != 0 { + echKeys := c.config.EncryptedClientHelloKeys + if c.config.GetEncryptedClientHelloKeys != nil { + echKeys, err = c.config.GetEncryptedClientHelloKeys(clientHelloInfo(ctx, c, clientHello)) + if err != nil { + c.sendAlert(alertInternalError) + return nil, nil, err + } + } + clientHello, ech, err = c.processECHClientHello(clientHello, echKeys) + if err != nil { + return nil, nil, err + } } var configForClient *Config @@ -151,7 +172,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { chi := clientHelloInfo(ctx, c, clientHello) if configForClient, err = c.config.GetConfigForClient(chi); err != nil { c.sendAlert(alertInternalError) - return nil, err + return nil, nil, err } else if configForClient != nil { c.config = configForClient } @@ -159,24 +180,44 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { c.ticketKeys = originalConfig.ticketKeys(configForClient) clientVersions := clientHello.supportedVersions - if len(clientHello.supportedVersions) == 0 { + if clientHello.vers >= VersionTLS13 && len(clientVersions) == 0 { + // RFC 8446 4.2.1 indicates when the supported_versions extension is not sent, + // compatible servers MUST negotiate TLS 1.2 or earlier if supported, even + // if the client legacy version is TLS 1.3 or later. + // + // Since we reject empty extensionSupportedVersions in the client hello unmarshal + // finding the supportedVersions empty indicates the extension was not present. + clientVersions = supportedVersionsFromMax(VersionTLS12) + } else if len(clientVersions) == 0 { clientVersions = supportedVersionsFromMax(clientHello.vers) } c.vers, ok = c.config.mutualVersion(roleServer, clientVersions) if !ok { c.sendAlert(alertProtocolVersion) - return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) + return nil, nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) } c.haveVers = true c.in.version = c.vers c.out.version = c.vers + // This check reflects some odd specification implied behavior. Client-facing servers + // are supposed to reject hellos with outer ECH and inner ECH that offers 1.2, but + // backend servers are allowed to accept hellos with inner ECH that offer 1.2, since + // they cannot expect client-facing servers to behave properly. Since we act as both + // a client-facing and backend server, we only enforce 1.3 being negotiated if we + // saw a hello with outer ECH first. The spec probably should've made this an error, + // but it didn't, and this matches the boringssl behavior. + if c.vers != VersionTLS13 && (ech != nil && !ech.inner) { + c.sendAlert(alertIllegalParameter) + return nil, nil, errors.New("tls: Encrypted Client Hello cannot be used pre-TLS 1.3") + } + if c.config.MinVersion == 0 && c.vers < VersionTLS12 { tls10server.Value() // ensure godebug is initialized tls10server.IncNonDefault() } - return clientHello, nil + return clientHello, ech, nil } func (hs *serverHandshakeState) processClientHello() error { @@ -195,7 +236,7 @@ func (hs *serverHandshakeState) processClientHello() error { } if !foundCompression { - c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertIllegalParameter) return errors.New("tls: client does not support uncompressed connections") } @@ -250,7 +291,11 @@ func (hs *serverHandshakeState) processClientHello() error { hs.hello.scts = hs.cert.SignedCertificateTimestamps } - hs.ecdheOk = supportsECDHE(c.config, c.vers, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) + hs.ecdheOk, err = supportsECDHE(c.config, c.vers, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) + if err != nil { + c.sendAlert(alertMissingExtension) + return err + } if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 { // Although omitting the ec_point_formats extension is permitted, some @@ -321,7 +366,7 @@ func negotiateALPN(serverProtos, clientProtos []string, quic bool) (string, erro // supportsECDHE returns whether ECDHE key exchanges can be used with this // pre-TLS 1.3 client. -func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, supportedPoints []uint8) bool { +func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, supportedPoints []uint8) (bool, error) { supportsCurve := false for _, curve := range supportedCurves { if c.supportsCurve(version, curve) { @@ -331,10 +376,12 @@ func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, support } supportsPointFormat := false + offeredNonCompressedFormat := false for _, pointFormat := range supportedPoints { if pointFormat == pointFormatUncompressed { supportsPointFormat = true - break + } else { + offeredNonCompressedFormat = true } } // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is @@ -343,42 +390,31 @@ func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, support // the parser. See https://go.dev/issue/49126. if len(supportedPoints) == 0 { supportsPointFormat = true + } else if offeredNonCompressedFormat && !supportsPointFormat { + return false, errors.New("tls: client offered only incompatible point formats") } - return supportsCurve && supportsPointFormat + return supportsCurve && supportsPointFormat, nil } func (hs *serverHandshakeState) pickCipherSuite() error { c := hs.c - preferenceOrder := cipherSuitesPreferenceOrder - if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { - preferenceOrder = cipherSuitesPreferenceOrderNoAES - } - - configCipherSuites := c.config.cipherSuites() - preferenceList := make([]uint16, 0, len(configCipherSuites)) - for _, suiteID := range preferenceOrder { - for _, id := range configCipherSuites { - if id == suiteID { - preferenceList = append(preferenceList, id) - break - } - } - } + preferenceList := c.config.cipherSuites(isAESGCMPreferred(hs.clientHello.cipherSuites)) hs.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk) if hs.suite == nil { c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no cipher suite supported by both client and server") + return fmt.Errorf("tls: no cipher suite supported by both client and server; client offered: %x", + hs.clientHello.cipherSuites) } c.cipherSuite = hs.suite.id - if c.config.CipherSuites == nil && !needFIPS() && rsaKexCiphers[hs.suite.id] { + if c.config.CipherSuites == nil && !fips140tls.Required() && rsaKexCiphers[hs.suite.id] { tlsrsakex.Value() // ensure godebug is initialized tlsrsakex.IncNonDefault() } - if c.config.CipherSuites == nil && !needFIPS() && tdesCiphers[hs.suite.id] { + if c.config.CipherSuites == nil && !fips140tls.Required() && tdesCiphers[hs.suite.id] { tls3des.Value() // ensure godebug is initialized tls3des.IncNonDefault() } @@ -475,7 +511,7 @@ func (hs *serverHandshakeState) checkForResumption() error { // Check that we also support the ciphersuite from the session. suite := selectCipherSuite([]uint16{sessionState.cipherSuite}, - c.config.cipherSuites(), hs.cipherSuiteOk) + c.config.supportedCipherSuites(), hs.cipherSuiteOk) if suite == nil { return nil } @@ -505,6 +541,10 @@ func (hs *serverHandshakeState) checkForResumption() error { // weird downgrade in client capabilities. return errors.New("tls: session supported extended_master_secret but client does not") } + if !sessionState.extMasterSecret && fips140tls.Required() { + // FIPS 140-3 requires the use of Extended Master Secret. + return nil + } c.peerCertificates = sessionState.peerCertificates c.ocspResponse = sessionState.ocspResponse @@ -513,6 +553,7 @@ func (hs *serverHandshakeState) checkForResumption() error { c.extMasterSecret = sessionState.extMasterSecret hs.sessionState = sessionState hs.suite = suite + c.curveID = sessionState.curveID c.didResume = true return nil } @@ -557,6 +598,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { hs.hello.ocspStapling = true } + if hs.clientHello.serverName != "" { + hs.hello.serverNameAck = true + } + hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled hs.hello.cipherSuite = hs.suite.id @@ -594,8 +639,9 @@ func (hs *serverHandshakeState) doFullHandshake() error { return err } if skx != nil { - if len(skx.key) >= 3 && skx.key[0] == 3 /* named curve */ { - c.curveID = CurveID(byteorder.BeUint16(skx.key[1:])) + if keyAgreement, ok := keyAgreement.(*ecdheKeyAgreement); ok { + c.curveID = keyAgreement.curveID + c.peerSigAlg = keyAgreement.signatureAlgorithm } if _, err := hs.c.writeHandshakeRecord(skx, &hs.finishedHash); err != nil { return err @@ -612,7 +658,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { } if c.vers >= VersionTLS12 { certReq.hasSignatureAlgorithm = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers) } // An empty list of certificateAuthorities signals to @@ -683,7 +729,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers) if err != nil { - c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertIllegalParameter) return err } if hs.hello.extendedMasterSecret { @@ -691,6 +737,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash.Sum()) } else { + if fips140tls.Required() { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: FIPS 140-3 requires the use of Extended Master Secret") + } hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) } @@ -730,6 +780,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { if err != nil { return c.sendAlert(alertInternalError) } + if sigHash == crypto.SHA1 { + tlssha1.Value() // ensure godebug is initialized + tlssha1.IncNonDefault() + } } else { sigType, sigHash, err = legacyTypeAndHashFromPublicKey(pub) if err != nil { @@ -743,6 +797,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { c.sendAlert(alertDecryptError) return errors.New("tls: invalid signature by the client certificate: " + err.Error()) } + c.peerSigAlg = certVerify.signatureAlgorithm if err := transcriptMsg(certVerify, &hs.finishedHash); err != nil { return err @@ -872,14 +927,14 @@ func (hs *serverHandshakeState) sendFinished(out []byte) error { } // processCertsFromClient takes a chain of client certificates either from a -// Certificates message and verifies them. +// certificateMsg message or a certificateMsgTLS13 message and verifies them. func (c *Conn) processCertsFromClient(certificate Certificate) error { certificates := certificate.Certificate certs := make([]*x509.Certificate, len(certificates)) var err error for i, asn1Data := range certificates { if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { - c.sendAlert(alertBadCertificate) + c.sendAlert(alertDecodeError) return errors.New("tls: failed to parse client certificate: " + err.Error()) } if certs[i].PublicKeyAlgorithm == x509.RSA { @@ -895,7 +950,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { if c.vers == VersionTLS13 { c.sendAlert(alertCertificateRequired) } else { - c.sendAlert(alertBadCertificate) + c.sendAlert(alertHandshakeFailure) } return errors.New("tls: client didn't provide a certificate") } @@ -912,7 +967,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { opts.Intermediates.AddCert(cert) } - chains, _, _, err := certs[0].Verify(opts) + chains, expired, never, err := certs[0].Verify(opts) if err != nil { var errCertificateInvalid x509.CertificateInvalidError if errors.As(err, &x509.UnknownAuthorityError{}) { @@ -925,7 +980,13 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} } - c.verifiedChains = chains + chains = append(chains, expired...) + chains = append(chains, never...) + c.verifiedChains, err = fipsAllowedChains(chains) + if err != nil { + c.sendAlert(alertBadCertificate) + return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} + } } c.peerCertificates = certs diff --git a/crypto/tls/handshake_server_test.go b/crypto/tls/handshake_server_test.go index 1812eecd72d..2657c42907a 100644 --- a/crypto/tls/handshake_server_test.go +++ b/crypto/tls/handshake_server_test.go @@ -27,6 +27,7 @@ import ( "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdh" "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" ) @@ -56,12 +57,13 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa }() ctx := context.Background() conn := Server(s, serverConfig) - ch, err := conn.readClientHello(ctx) + ch, ech, err := conn.readClientHello(ctx) if conn.vers == VersionTLS13 { hs := serverHandshakeStateTLS13{ c: conn, ctx: ctx, clientHello: ch, + echContext: ech, } if err == nil { err = hs.processClientHello() @@ -120,7 +122,7 @@ func TestRejectBadProtocolVersion(t *testing.T) { func TestNoSuiteOverlap(t *testing.T) { clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), cipherSuites: []uint16{0xff00}, compressionMethods: []uint8{compressionNone}, @@ -130,9 +132,9 @@ func TestNoSuiteOverlap(t *testing.T) { func TestNoCompressionOverlap(t *testing.T) { clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{0xff}, } testClientHelloFailure(t, testConfig, clientHello, "client does not support uncompressed connections") @@ -140,7 +142,7 @@ func TestNoCompressionOverlap(t *testing.T) { func TestNoRC4ByDefault(t *testing.T) { clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, compressionMethods: []uint8{compressionNone}, @@ -157,16 +159,16 @@ func TestRejectSNIWithTrailingDot(t *testing.T) { vers: VersionTLS12, random: make([]byte, 32), serverName: "foo.com.", - }, "unexpected message") + }, "decoding message") } func TestDontSelectECDSAWithRSAKey(t *testing.T) { // Test that, even when both sides support an ECDSA cipher suite, it // won't be selected if the server's private key doesn't support it. clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, compressionMethods: []uint8{compressionNone}, supportedCurves: []CurveID{CurveP256}, supportedPoints: []uint8{pointFormatUncompressed}, @@ -190,9 +192,9 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) { // Test that, even when both sides support an RSA cipher suite, it // won't be selected if the server's private key doesn't support it. clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, supportedCurves: []CurveID{CurveP256}, supportedPoints: []uint8{pointFormatUncompressed}, @@ -212,6 +214,8 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) { } func TestRenegotiationExtension(t *testing.T) { + skipFIPS(t) // #70505 + clientHello := &clientHelloMsg{ vers: VersionTLS12, compressionMethods: []uint8{compressionNone}, @@ -234,7 +238,6 @@ func TestRenegotiationExtension(t *testing.T) { n, err := c.Read(buf) if err != nil { t.Errorf("Server read returned error: %s", err) - return } c.Close() bufChan <- buf[:n] @@ -264,6 +267,8 @@ func TestRenegotiationExtension(t *testing.T) { } func TestTLS12OnlyCipherSuites(t *testing.T) { + skipFIPS(t) // No TLS 1.1 in FIPS mode. + // Test that a Server doesn't select a TLS 1.2-only cipher suite when // the client negotiates TLS 1.1. clientHello := &clientHelloMsg{ @@ -325,13 +330,18 @@ func TestTLSPointFormats(t *testing.T) { supportedPoints []uint8 wantSupportedPoints bool }{ - {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true}, - {"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, nil, false}, - {"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true}, + {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true}, + {"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, []CurveID{CurveP256}, nil, false}, + {"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true}, {"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false}, {"RSA with ec_point_format", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, []uint8{pointFormatUncompressed}, false}, } for _, tt := range tests { + // The RSA subtests should be enabled for FIPS 140 required mode: #70505 + if strings.HasPrefix(tt.name, "RSA") && fips140tls.Required() { + t.Logf("skipping in FIPS mode.") + continue + } t.Run(tt.name, func(t *testing.T) { clientHello := &clientHelloMsg{ vers: VersionTLS12, @@ -345,7 +355,9 @@ func TestTLSPointFormats(t *testing.T) { c, s := localPipe(t) replyChan := make(chan any) go func() { - cli := Client(c, testConfig) + clientConfig := testConfig.Clone() + clientConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} + cli := Client(c, clientConfig) cli.vers = clientHello.vers if _, err := cli.writeHandshakeRecord(clientHello, nil); err != nil { testFatal(t, err) @@ -358,9 +370,10 @@ func TestTLSPointFormats(t *testing.T) { replyChan <- reply } }() - config := testConfig.Clone() - config.CipherSuites = clientHello.cipherSuites - Server(s, config).Handshake() + serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} + serverConfig.CipherSuites = clientHello.cipherSuites + Server(s, serverConfig).Handshake() s.Close() reply := <-replyChan if err, ok := reply.(error); ok { @@ -435,6 +448,8 @@ func TestVersion(t *testing.T) { } func TestCipherSuitePreference(t *testing.T) { + skipFIPS(t) // No RC4 or CHACHA20_POLY1305 in FIPS mode. + serverConfig := &Config{ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, @@ -503,15 +518,17 @@ func TestCrossVersionResume(t *testing.T) { func testCrossVersionResume(t *testing.T, version uint16) { serverConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, Certificates: testConfig.Certificates, + Time: testTime, } clientConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, InsecureSkipVerify: true, ClientSessionCache: NewLRUClientSessionCache(1), ServerName: "servername", MinVersion: VersionTLS12, + Time: testTime, } // Establish a session at TLS 1.3. @@ -720,7 +737,7 @@ func (test *serverTest) run(t *testing.T, write bool) { t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", test.name, len(test.expectedPeerCerts), len(peerCerts)) } - if test.validate != nil { + if test.validate != nil && !t.Failed() { if err := test.validate(connState); err != nil { t.Fatalf("validate callback returned error: %s", err) } @@ -925,22 +942,6 @@ func TestHandshakeServerKeySharePreference(t *testing.T) { runServerTestTLS13(t, test) } -// TestHandshakeServerUnsupportedKeyShare tests a client that sends a key share -// that's not in the supported groups list. -func TestHandshakeServerUnsupportedKeyShare(t *testing.T) { - pk, _ := ecdh.X25519().GenerateKey(rand.Reader) - clientHello := &clientHelloMsg{ - vers: VersionTLS12, - random: make([]byte, 32), - supportedVersions: []uint16{VersionTLS13}, - cipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256}, - compressionMethods: []uint8{compressionNone}, - keyShares: []keyShare{{group: X25519, data: pk.PublicKey().Bytes()}}, - supportedCurves: []CurveID{CurveP256}, - } - testClientHelloFailure(t, testConfig, clientHello, "client sent key share for group it does not support") -} - func TestHandshakeServerALPN(t *testing.T) { config := testConfig.Clone() config.NextProtos = []string{"proto1", "proto2"} @@ -1082,16 +1083,16 @@ func TestHandshakeServerGetCertificateExtensions(t *testing.T) { testVersions := []uint16{VersionTLS12, VersionTLS13} for _, vers := range testVersions { t.Run(fmt.Sprintf("TLS version %04x", vers), func(t *testing.T) { - pk, _ := ecdh.X25519().GenerateKey(rand.Reader) + pk, _ := ecdh.P256().GenerateKey(rand.Reader) clientHello := &clientHelloMsg{ vers: vers, random: make([]byte, 32), - cipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256}, + cipherSuites: []uint16{TLS_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, serverName: "test", - keyShares: []keyShare{{group: X25519, data: pk.PublicKey().Bytes()}}, - supportedCurves: []CurveID{X25519}, - supportedSignatureAlgorithms: []SignatureScheme{Ed25519}, + keyShares: []keyShare{{group: CurveP256, data: pk.PublicKey().Bytes()}}, + supportedCurves: []CurveID{CurveP256}, + supportedSignatureAlgorithms: []SignatureScheme{ECDSAWithP256AndSHA256}, } // the clientHelloMsg initialized just above is serialized with @@ -1140,9 +1141,9 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) { } clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, serverName: "test", } @@ -1161,9 +1162,9 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) { serverConfig.Certificates = nil clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, } testClientHelloFailure(t, serverConfig, clientHello, errMsg) @@ -1173,9 +1174,9 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) { serverConfig.GetCertificate = nil clientHello = &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, } testClientHelloFailure(t, serverConfig, clientHello, "no certificates") @@ -1498,9 +1499,9 @@ func TestSNIGivenOnFailure(t *testing.T) { const expectedServerName = "test.testing" clientHello := &clientHelloMsg{ - vers: VersionTLS10, + vers: VersionTLS12, random: make([]byte, 32), - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, compressionMethods: []uint8{compressionNone}, serverName: expectedServerName, } @@ -1520,7 +1521,7 @@ func TestSNIGivenOnFailure(t *testing.T) { }() conn := Server(s, serverConfig) ctx := context.Background() - ch, err := conn.readClientHello(ctx) + ch, _, err := conn.readClientHello(ctx) hs := serverHandshakeState{ c: conn, ctx: ctx, @@ -1756,7 +1757,7 @@ T+E0J8wlH24pgwQHzy7Ko2qLwn1b5PW8ecrlvP1g func TestMultipleCertificates(t *testing.T) { clientConfig := testConfig.Clone() - clientConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256} + clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} clientConfig.MaxVersion = VersionTLS12 serverConfig := testConfig.Clone() @@ -1778,6 +1779,8 @@ func TestMultipleCertificates(t *testing.T) { } func TestAESCipherReordering(t *testing.T) { + skipFIPS(t) // No CHACHA20_POLY1305 for FIPS. + currentAESSupport := hasAESGCMHardwareSupport defer func() { hasAESGCMHardwareSupport = currentAESSupport }() @@ -1921,6 +1924,8 @@ func TestAESCipherReordering(t *testing.T) { } func TestAESCipherReorderingTLS13(t *testing.T) { + skipFIPS(t) // No CHACHA20_POLY1305 for FIPS. + currentAESSupport := hasAESGCMHardwareSupport defer func() { hasAESGCMHardwareSupport = currentAESSupport }() @@ -2041,8 +2046,8 @@ func TestServerHandshakeContextCancellation(t *testing.T) { if err != context.Canceled { t.Errorf("Unexpected server handshake error: %v", err) } - if runtime.GOARCH == "wasm" { - t.Skip("conn.Close does not error as expected when called multiple times on WASM") + if runtime.GOOS == "js" || runtime.GOOS == "wasip1" { + t.Skip("conn.Close does not error as expected when called multiple times on GOOS=js or GOOS=wasip1") } err = conn.Close() if err == nil { diff --git a/crypto/tls/handshake_server_tls13.go b/crypto/tls/handshake_server_tls13.go index 6e3b5fe82dc..0106abd8568 100644 --- a/crypto/tls/handshake_server_tls13.go +++ b/crypto/tls/handshake_server_tls13.go @@ -8,15 +8,23 @@ import ( "bytes" "context" "errors" - "hash" + "fmt" "io" "slices" + "sort" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" + + "github.com/runZeroInc/excrypto/crypto/hkdf" "github.com/runZeroInc/excrypto/crypto/hmac" - "github.com/runZeroInc/excrypto/crypto/internal/mlkem768" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls13" + "github.com/runZeroInc/excrypto/crypto/internal/hpke" "github.com/runZeroInc/excrypto/crypto/rsa" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/internal/byteorder" ) @@ -25,6 +33,18 @@ import ( // messages cause too much work in session ticket decryption attempts. const maxClientPSKIdentities = 5 +type echServerContext struct { + hpkeContext *hpke.Recipient + configID uint8 + ciphersuite echCipher + transcript hash.Hash + // inner indicates that the initial client_hello we recieved contained an + // encrypted_client_hello extension that indicated it was an "inner" hello. + // We don't do any additional processing of the hello in this case, so all + // fields above are unset. + inner bool +} + type serverHandshakeStateTLS13 struct { c *Conn ctx context.Context @@ -36,13 +56,14 @@ type serverHandshakeStateTLS13 struct { suite *cipherSuiteTLS13 cert *Certificate sigAlg SignatureScheme - earlySecret []byte + earlySecret *tls13.EarlySecret sharedKey []byte - handshakeSecret []byte - masterSecret []byte + handshakeSecret *tls13.HandshakeSecret + masterSecret *tls13.MasterSecret trafficSecret []byte // client_application_traffic_secret_0 transcript hash.Hash clientFinished []byte + echContext *echServerContext } func (hs *serverHandshakeStateTLS13) handshake() error { @@ -159,11 +180,11 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { hs.hello.compressionMethod = compressionNone preferenceList := defaultCipherSuitesTLS13 - if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { + if !hasAESGCMHardwareSupport || !isAESGCMPreferred(hs.clientHello.cipherSuites) { preferenceList = defaultCipherSuitesTLS13NoAES } - if needFIPS() { - preferenceList = defaultCipherSuitesTLS13FIPS + if fips140tls.Required() { + preferenceList = allowedCipherSuitesTLS13FIPS } for _, suiteID := range preferenceList { hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID) @@ -173,42 +194,51 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { } if hs.suite == nil { c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no cipher suite supported by both client and server") + return fmt.Errorf("tls: no cipher suite supported by both client and server; client offered: %x", + hs.clientHello.cipherSuites) } c.cipherSuite = hs.suite.id hs.hello.cipherSuite = hs.suite.id hs.transcript = hs.suite.hash.New() - // Pick the key exchange method in server preference order, but give - // priority to key shares, to avoid a HelloRetryRequest round-trip. - var selectedGroup CurveID - var clientKeyShare *keyShare + // First, if a post-quantum key exchange is available, use one. See + // draft-ietf-tls-key-share-prediction-01, Section 4 for why this must be + // first. + // + // Second, if the client sent a key share for a group we support, use that, + // to avoid a HelloRetryRequest round-trip. + // + // Finally, pick in our fixed preference order. preferredGroups := c.config.curvePreferences(c.vers) - for _, preferredGroup := range preferredGroups { - ki := slices.IndexFunc(hs.clientHello.keyShares, func(ks keyShare) bool { - return ks.group == preferredGroup - }) - if ki != -1 { - clientKeyShare = &hs.clientHello.keyShares[ki] - selectedGroup = clientKeyShare.group - if !slices.Contains(hs.clientHello.supportedCurves, selectedGroup) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client sent key share for group it does not support") - } - break - } + preferredGroups = slices.DeleteFunc(preferredGroups, func(group CurveID) bool { + return !slices.Contains(hs.clientHello.supportedCurves, group) + }) + if len(preferredGroups) == 0 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: no key exchanges supported by both client and server") } - if selectedGroup == 0 { - for _, preferredGroup := range preferredGroups { - if slices.Contains(hs.clientHello.supportedCurves, preferredGroup) { - selectedGroup = preferredGroup - break + hasKeyShare := func(group CurveID) bool { + for _, ks := range hs.clientHello.keyShares { + if ks.group == group { + return true } } + return false } - if selectedGroup == 0 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no ECDHE curve supported by both client and server") + sort.SliceStable(preferredGroups, func(i, j int) bool { + return hasKeyShare(preferredGroups[i]) && !hasKeyShare(preferredGroups[j]) + }) + sort.SliceStable(preferredGroups, func(i, j int) bool { + return isPQKeyExchange(preferredGroups[i]) && !isPQKeyExchange(preferredGroups[j]) + }) + selectedGroup := preferredGroups[0] + + var clientKeyShare *keyShare + for _, ks := range hs.clientHello.keyShares { + if ks.group == selectedGroup { + clientKeyShare = &ks + break + } } if clientKeyShare == nil { ks, err := hs.doHelloRetryRequest(selectedGroup) @@ -221,13 +251,13 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { ecdhGroup := selectedGroup ecdhData := clientKeyShare.data - if selectedGroup == x25519Kyber768Draft00 { + if selectedGroup == X25519MLKEM768 { ecdhGroup = X25519 - if len(ecdhData) != x25519PublicKeySize+mlkem768.EncapsulationKeySize { + if len(ecdhData) != mlkem.EncapsulationKeySize768+x25519PublicKeySize { c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid Kyber client key share") + return errors.New("tls: invalid X25519MLKEM768 client key share") } - ecdhData = ecdhData[:x25519PublicKeySize] + ecdhData = ecdhData[mlkem.EncapsulationKeySize768:] } if _, ok := curveForCurveID(ecdhGroup); !ok { c.sendAlert(alertInternalError) @@ -249,14 +279,24 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: invalid client key share") } - if selectedGroup == x25519Kyber768Draft00 { - ciphertext, kyberShared, err := kyberEncapsulate(clientKeyShare.data[x25519PublicKeySize:]) + if selectedGroup == X25519MLKEM768 { + k, err := mlkem.NewEncapsulationKey768(clientKeyShare.data[:mlkem.EncapsulationKeySize768]) if err != nil { c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid Kyber client key share") + return errors.New("tls: invalid X25519MLKEM768 client key share") } - hs.sharedKey = append(hs.sharedKey, kyberShared...) - hs.hello.serverShare.data = append(hs.hello.serverShare.data, ciphertext...) + mlkemSharedSecret, ciphertext := k.Encapsulate() + // draft-kwiatkowski-tls-ecdhe-mlkem-02, Section 3.1.3: "For + // X25519MLKEM768, the shared secret is the concatenation of the ML-KEM + // shared secret and the X25519 shared secret. The shared secret is 64 + // bytes (32 bytes for each part)." + hs.sharedKey = append(mlkemSharedSecret, hs.sharedKey...) + // draft-kwiatkowski-tls-ecdhe-mlkem-02, Section 3.1.2: "When the + // X25519MLKEM768 group is negotiated, the server's key exchange value + // is the concatenation of an ML-KEM ciphertext returned from + // encapsulation to the client's encapsulation key, and the server's + // ephemeral X25519 share." + hs.hello.serverShare.data = append(ciphertext, hs.hello.serverShare.data...) } selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil) @@ -383,8 +423,8 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { } } - hs.earlySecret = hs.suite.extract(sessionState.secret, nil) - binderKey := hs.suite.deriveSecret(hs.earlySecret, resumptionBinderLabel, nil) + hs.earlySecret = tls13.NewEarlySecret(hs.suite.hash.New, sessionState.secret) + binderKey := hs.earlySecret.ResumptionBinderKey() // Clone the transcript in case a HelloRetryRequest was recorded. transcript := cloneHash(hs.transcript, hs.suite.hash) if transcript == nil { @@ -412,7 +452,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { if err := transcriptMsg(hs.clientHello, transcript); err != nil { return err } - earlyTrafficSecret := hs.suite.deriveSecret(hs.earlySecret, clientEarlyTrafficLabel, transcript) + earlyTrafficSecret := hs.earlySecret.ClientEarlyTrafficSecret(transcript) c.quicSetReadSecret(QUICEncryptionLevelEarly, hs.suite.id, earlyTrafficSecret) } @@ -530,6 +570,23 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) selectedGroup: selectedGroup, } + if hs.echContext != nil { + // Compute the acceptance message. + helloRetryRequest.encryptedClientHello = make([]byte, 8) + confTranscript := cloneHash(hs.transcript, hs.suite.hash) + if err := transcriptMsg(helloRetryRequest, confTranscript); err != nil { + return nil, err + } + h := hs.suite.hash.New + prf, err := hkdf.Extract(h, hs.clientHello.random, nil) + if err != nil { + c.sendAlert(alertInternalError) + return nil, err + } + acceptConfirmation := tls13.ExpandLabel(h, prf, "hrr ech accept confirmation", confTranscript.Sum(nil), 8) + helloRetryRequest.encryptedClientHello = acceptConfirmation + } + if _, err := hs.c.writeHandshakeRecord(helloRetryRequest, hs.transcript); err != nil { return nil, err } @@ -550,6 +607,45 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) return nil, unexpectedMessageError(clientHello, msg) } + if hs.echContext != nil { + if len(clientHello.encryptedClientHello) == 0 { + c.sendAlert(alertMissingExtension) + return nil, errors.New("tls: second client hello missing encrypted client hello extension") + } + + echType, echCiphersuite, configID, encap, payload, err := parseECHExt(clientHello.encryptedClientHello) + if err != nil { + c.sendAlert(alertDecodeError) + return nil, errors.New("tls: client sent invalid encrypted client hello extension") + } + + if echType == outerECHExt && hs.echContext.inner || echType == innerECHExt && !hs.echContext.inner { + c.sendAlert(alertDecodeError) + return nil, errors.New("tls: unexpected switch in encrypted client hello extension type") + } + + if echType == outerECHExt { + if echCiphersuite != hs.echContext.ciphersuite || configID != hs.echContext.configID || len(encap) != 0 { + c.sendAlert(alertIllegalParameter) + return nil, errors.New("tls: second client hello encrypted client hello extension does not match") + } + + encodedInner, err := decryptECHPayload(hs.echContext.hpkeContext, clientHello.original, payload) + if err != nil { + c.sendAlert(alertDecryptError) + return nil, errors.New("tls: failed to decrypt second client hello encrypted client hello extension payload") + } + + echInner, err := decodeInnerClientHello(clientHello, encodedInner) + if err != nil { + c.sendAlert(alertIllegalParameter) + return nil, errors.New("tls: client sent invalid encrypted client hello extension") + } + + clientHello = echInner + } + } + if len(clientHello.keyShares) != 1 { c.sendAlert(alertIllegalParameter) return nil, errors.New("tls: client didn't send one key share in second ClientHello") @@ -637,9 +733,28 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { func (hs *serverHandshakeStateTLS13) sendServerParameters() error { c := hs.c + if hs.echContext != nil { + copy(hs.hello.random[32-8:], make([]byte, 8)) + echTranscript := cloneHash(hs.transcript, hs.suite.hash) + echTranscript.Write(hs.clientHello.original) + if err := transcriptMsg(hs.hello, echTranscript); err != nil { + return err + } + // compute the acceptance message + h := hs.suite.hash.New + prk, err := hkdf.Extract(h, hs.clientHello.random, nil) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + acceptConfirmation := tls13.ExpandLabel(h, prk, "ech accept confirmation", echTranscript.Sum(nil), 8) + copy(hs.hello.random[32-8:], acceptConfirmation) + } + if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil { return err } + if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil { return err } @@ -650,16 +765,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { earlySecret := hs.earlySecret if earlySecret == nil { - earlySecret = hs.suite.extract(nil, nil) + earlySecret = tls13.NewEarlySecret(hs.suite.hash.New, nil) } - hs.handshakeSecret = hs.suite.extract(hs.sharedKey, - hs.suite.deriveSecret(earlySecret, "derived", nil)) + hs.handshakeSecret = earlySecret.HandshakeSecret(hs.sharedKey) - clientSecret := hs.suite.deriveSecret(hs.handshakeSecret, - clientHandshakeTrafficLabel, hs.transcript) + clientSecret := hs.handshakeSecret.ClientHandshakeTrafficSecret(hs.transcript) c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret) - serverSecret := hs.suite.deriveSecret(hs.handshakeSecret, - serverHandshakeTrafficLabel, hs.transcript) + serverSecret := hs.handshakeSecret.ServerHandshakeTrafficSecret(hs.transcript) c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret) if c.quic != nil { @@ -693,6 +805,28 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { encryptedExtensions.earlyData = hs.earlyData } + if !hs.c.didResume && hs.clientHello.serverName != "" { + encryptedExtensions.serverNameAck = true + } + + // If client sent ECH extension, but we didn't accept it, + // send retry configs, if available. + echKeys := hs.c.config.EncryptedClientHelloKeys + if hs.c.config.GetEncryptedClientHelloKeys != nil { + echKeys, err = hs.c.config.GetEncryptedClientHelloKeys(clientHelloInfo(hs.ctx, c, hs.clientHello)) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + } + if len(echKeys) > 0 && len(hs.clientHello.encryptedClientHello) > 0 && hs.echContext == nil { + encryptedExtensions.echRetryConfigs, err = buildRetryConfigList(echKeys) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + } + if _, err := hs.c.writeHandshakeRecord(encryptedExtensions, hs.transcript); err != nil { return err } @@ -717,7 +851,8 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certReq := new(certificateRequestMsgTLS13) certReq.ocspStapling = true certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(c.vers) + certReq.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert() if c.config.ClientCAs != nil { certReq.certificateAuthorities = c.config.ClientCAs.Subjects() } @@ -784,13 +919,10 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error { // Derive secrets that take context through the server Finished. - hs.masterSecret = hs.suite.extract(nil, - hs.suite.deriveSecret(hs.handshakeSecret, "derived", nil)) + hs.masterSecret = hs.handshakeSecret.MasterSecret() - hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, - clientApplicationTrafficLabel, hs.transcript) - serverSecret := hs.suite.deriveSecret(hs.masterSecret, - serverApplicationTrafficLabel, hs.transcript) + hs.trafficSecret = hs.masterSecret.ClientApplicationTrafficSecret(hs.transcript) + serverSecret := hs.masterSecret.ServerApplicationTrafficSecret(hs.transcript) c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret) if c.quic != nil { @@ -837,12 +969,7 @@ func (hs *serverHandshakeStateTLS13) shouldSendSessionTickets() bool { } // Don't send tickets the client wouldn't use. See RFC 8446, Section 4.2.9. - for _, pskMode := range hs.clientHello.pskModes { - if pskMode == pskModeDHE { - return true - } - } - return false + return slices.Contains(hs.clientHello.pskModes, pskModeDHE) } func (hs *serverHandshakeStateTLS13) sendSessionTickets() error { @@ -856,8 +983,7 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error { return err } - c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, - resumptionLabel, hs.transcript) + c.resumptionSecret = hs.masterSecret.ResumptionMasterSecret(hs.transcript) if !hs.shouldSendSessionTickets() { return nil @@ -872,7 +998,7 @@ func (c *Conn) sendSessionTicket(earlyData bool, extra [][]byte) error { } // ticket_nonce, which must be unique per connection, is always left at // zero because we only ever send one ticket per connection. - psk := suite.expandLabel(c.resumptionSecret, "resumption", + psk := tls13.ExpandLabel(suite.hash.New, c.resumptionSecret, "resumption", nil, suite.hash.Size()) m := new(newSessionTicketMsgTLS13) @@ -907,7 +1033,7 @@ func (c *Conn) sendSessionTicket(earlyData bool, extra [][]byte) error { if _, err := c.config.rand().Read(ageAdd); err != nil { return err } - m.ageAdd = byteorder.LeUint32(ageAdd) + m.ageAdd = byteorder.LEUint32(ageAdd) if earlyData { // RFC 9001, Section 4.6.1 @@ -977,7 +1103,10 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { + // We don't use certReq.supportedSignatureAlgorithms because it would + // require keeping the certificateRequestMsgTLS13 around in the hs. + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers)) || + !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, signatureSchemesForPublicKey(c.vers, c.peerCertificates[0].PublicKey)) { c.sendAlert(alertIllegalParameter) return errors.New("tls: client certificate used with invalid signature algorithm") } @@ -986,8 +1115,7 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { return c.sendAlert(alertInternalError) } if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client certificate used with invalid signature algorithm") + return c.sendAlert(alertInternalError) } signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, @@ -995,6 +1123,7 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { c.sendAlert(alertDecryptError) return errors.New("tls: invalid signature by the client certificate: " + err.Error()) } + c.peerSigAlg = certVerify.signatureAlgorithm if err := transcriptMsg(certVerify, hs.transcript); err != nil { return err diff --git a/crypto/tls/handshake_test.go b/crypto/tls/handshake_test.go index 5c47acc94a4..4d26f729ca0 100644 --- a/crypto/tls/handshake_test.go +++ b/crypto/tls/handshake_test.go @@ -11,8 +11,6 @@ import ( "errors" "flag" "fmt" - "github.com/runZeroInc/excrypto/crypto/ed25519" - "github.com/runZeroInc/excrypto/crypto/x509" "io" "net" "os" @@ -23,6 +21,9 @@ import ( "sync" "testing" "time" + + "github.com/runZeroInc/excrypto/crypto/ed25519" + "github.com/runZeroInc/excrypto/crypto/x509" ) // TLS reference tests run a connection against a reference implementation @@ -50,6 +51,9 @@ var ( ) func runTestAndUpdateIfNeeded(t *testing.T, name string, run func(t *testing.T, update bool), wait bool) { + // FIPS mode is non-deterministic and so isn't suited for testing against static test transcripts. + skipFIPS(t) + success := t.Run(name, func(t *testing.T) { if !*update && !wait { t.Parallel() @@ -519,10 +523,21 @@ func fromHex(s string) []byte { return b } +// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of +// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate], +// [testRSA2048CertificateIssuer], and [testECDSACertificate]. +var testTime = func() time.Time { return time.Unix(1476984729, 0) } + var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") +var testRSA2048Certificate = fromHex("30820316308201fea003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3338303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30820122300d06092a864886f70d01010105000382010f003082010a0282010100e0ac47db9ba1b7f98a996c62dc1d248d4ee570544136fe4e911e22fccc0fe2b20982f3c4cdd8f4065c5068c873ca0a768b80dc915edc66541a5f26cdea44e56e411221e2f9927bf4e009fee76dbe0e118dcc13392efd6f42d8eb2fd5bc8f63ac77800c84d3be90c20c321273254b9137ef61f825dad1ec2c5e75aa4be6d3104899bd5ac400da7ab942b4227a3870ae5bb97870aa09a1082fb8e78b944cd7fd1b0c6fb1cce03b5430b12ef9ce2d95e01821766e998df0cc99202a57cf030577bd2dc0ec85a49f203511bb6f0e9f43398ead0958f8d7534c61e81daf4501faaa68d9cbc725b58401900fa48a3e2333b15c88cf0c5cc8f33fb9464f9d5f5768b8f10203010001a35a3058300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b050003820101009e83f835e2da08204ee6f8bdca793cf83c7aec175349c1642dfbe9f4d0dcfb1aedb4d0122e16c2ad92e63dd31cce10ca5dd04be48cded0fdc8fea49e891d9d93e778a67d54b619ac167ce7bb0f6000ca00c5677d09df3eb10080134ba32bfe4132d33954dc479cb266288d53d3f43af9c78c0ca59d396498bdc56d4966dc6b7e49081f7f2ae1d704bb9f9effed93c57d3b738da02edff3999e3f1a5dce2b093951947d233d9c6b6a12b4b1611826aa02544980089eebbcf22a1a96bd35a3ddf638578989334a93d5081fab442b4383ba6213b7cdd74110582244a2abd937828b311d8dd69178756db7874293b9810c5c2e833f91d49d283a62caaf359141997f") + +var testRSA2048CertificateIssuer = fromHex("308203223082020aa003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430820122300d06092a864886f70d01010105000382010f003082010a0282010100b308c1720c7054abe66e1be6f8a11246808215a810e8936e47601f7ec1afeb02ad69a5000959d4e08ebc4455ef90b39616f380b8ff2e76f29942d7e009cf010824fe56f69140ac39b761595255ec2aa35155ca2eea884f57b25f8a52f41f56f65b0197cb6c637f9adfa97d8ac27565449f64e67f8b918646ffd630601b0badd8d38aea421fe413ee94f10ea5874c2fd6d8c1b9febaa5ca0ce759993a232c9c48e52230bbf58777b0c30e07e9e0914133730d844b9887b950d5a17c779ac69de2d9c65d26f1ea46c7dd7ac636af6d77df7c9218f78c7b5f08b025867f343ac66cd43a657ac44bfd7e9d07e95a22ff9a0babf72dcffc66eba0a1d90731f67e3bbd0203010001a361305f300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff301d0603551d0e0416041460145a6ce2e8a15b1b68db9a4752ce8684d6ba2d300d06092a864886f70d01010b050003820101001d342fe0b50a25d57a8b13bc14d0abb1eea7431ee752aa423e1306654183e44e9d48bbf592cd32ce77310fdc4e8bbcd724fc43d2723f454bfe605ff90d38d8c6fe60b36c6f4d2d7e4e79bceeb2484f0565274b0d0c4a8562370677624a4c133e332a9e63d4b47544c14e4908ee8685dd0760ae6f4ab089ede2b0cdc595ecefbee7d8be80d57b2d4e4510b6ceda54d1a5980540214191d81cc89a983da43d4043f8efe97a2e231c5153bded520acce87ec8c64a3408f0eb4c742c4a877e8b5b7b7f72497734a41a95994a7a103262ea6d598d03fd5cb0579ed4702424da8893334c58215bc655d49656aedcd02d18676f45d6b9469ae04b89abe9b358391cce99") + +var testRSA2048PrivateKey, _ = x509.ParsePKCS1PrivateKey(fromHex("308204a40201000282010100e0ac47db9ba1b7f98a996c62dc1d248d4ee570544136fe4e911e22fccc0fe2b20982f3c4cdd8f4065c5068c873ca0a768b80dc915edc66541a5f26cdea44e56e411221e2f9927bf4e009fee76dbe0e118dcc13392efd6f42d8eb2fd5bc8f63ac77800c84d3be90c20c321273254b9137ef61f825dad1ec2c5e75aa4be6d3104899bd5ac400da7ab942b4227a3870ae5bb97870aa09a1082fb8e78b944cd7fd1b0c6fb1cce03b5430b12ef9ce2d95e01821766e998df0cc99202a57cf030577bd2dc0ec85a49f203511bb6f0e9f43398ead0958f8d7534c61e81daf4501faaa68d9cbc725b58401900fa48a3e2333b15c88cf0c5cc8f33fb9464f9d5f5768b8f10203010001028201007aac96efca229b199e1bf79a63256677e1c455792bc2a348b2e409a68ea57dda486740430d4290bb885c3f5a741eb567d4f41f7b2098a726f4df4f88cf899edc7c9b31f584dffedece15a7212642c7dbbdd8d806392a183e1fc30af36169c9bab9e528f0bdcd27ad4c8b6a97849da6452c6809de61848db80c3ba3289e785042cdfd46fbfee5f78adcba2927fcd8cbe9dcaa97190457eaa45d77adbe0db820aff0c8511d837ab5b307bad5f85afd2cc70d9659ec58045d97ced1eb7950670ac559449c0305fddefda1bac88d36629a177f65abad182c6470830b39e7f6dbdef4df813ccaef01d5a42d37213b2b9647e2ff56a63e6b6a4b6e8a1567bbfd77042102818100eb66f205e8507c78f7167dbef3ddf02fde6a67bd15152609e9296576e28c79678177145ae98e0a2fee58fdb3d626fb6beae3e0ae0b76bc47d16fcdeb16f0caca8a0902779979382609705ae84514de480c2fb2ddda3049347cc1bde9f1a359747079ef3dce020a3c186c90e63bc20b5489a40d768b1c1c35c679edc5662e18c702818100f454ffff95b126b55cb13b68a3841600fc0bc69ff4064f7ceb122495fa972fdb05ca2fa1c6e2e84432f81c96875ab12226e8ce92ba808c4f6325f27ce058791f05db96e623687d3cfc198e748a07521a8c7ee9e7e8faf95b0985be82b867a49f7d5d50fac3881d2c39dedfdbca3ebe847b859c9864cf7a543e4688f5a60118870281806cee737ac65950704daeebbb8c701c709a54d4f28baa00b33f6137a1bf0e5033d4963d2620c3e8f4eb2fe51eee2f95d3079c31e1784e96ac093fdaa33a376d3032961ebd27990fa192669abab715041385082196461c6813d0d37ac5a25afbcf452937cb7ae438c63c6b28d651bae6b1550c446aa1cefd42e9388d0df6cdc80b02818100cac172c33504923bb494fad8e5c0a9c5dd63244bfe63f238969632b82700a95cd71c2694d887d9f92656d0da75ae640a1441e392cda3f94bb3da7cb4f6335527d2639c809467946e34423cfe26c0d6786398ba20922d1b1a59f79bd5bc937d8040b75c890c13fb298548977a3c05ff71cf535c54f66b5a77684a7e4363a3cb2702818100a4d782f35d5a07f9c1f8f9c378564b220387d1e481cc856b631de7637d8bb77c851db070122050ac230dc6e45edf4523471c717c1cb86a36b2fd3358fae349d51be54d71d7dbeaa6af668323e2b51933f0b8488aa12723e0f32207068b4aa64ed54bcef4acbbbe35b92802faba7ed45ae52bef8313d9ef4393ccc5cf868ddbf8")) + // testRSAPSSCertificate has signatureAlgorithm rsassaPss, but subjectPublicKeyInfo // algorithm rsaEncryption, for use with the rsa_pss_rsae_* SignatureSchemes. // See also TestRSAPSSKeyError. testRSAPSSCertificate is self-signed. diff --git a/crypto/tls/internal/fips140tls/fipstls.go b/crypto/tls/internal/fips140tls/fipstls.go new file mode 100644 index 00000000000..85d42471211 --- /dev/null +++ b/crypto/tls/internal/fips140tls/fipstls.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fips140tls controls whether crypto/tls requires FIPS-approved settings. +package fips140tls + +import ( + "sync/atomic" + + "github.com/runZeroInc/excrypto/crypto/fips140" +) + +var required atomic.Bool + +func init() { + if fips140.Enabled() { + Force() + } +} + +// Force forces crypto/tls to restrict TLS configurations to FIPS-approved settings. +// By design, this call is impossible to undo (except in tests). +func Force() { + required.Store(true) +} + +// Required reports whether FIPS-approved settings are required. +// +// Required is true if FIPS 140-3 mode is enabled with GODEBUG=fips140=on, or if +// the crypto/tls/fipsonly package is imported by a Go+BoringCrypto build. +func Required() bool { + return required.Load() +} + +func TestingOnlyAbandon() { + required.Store(false) +} diff --git a/crypto/tls/key_agreement.go b/crypto/tls/key_agreement.go index aed262cc5cd..6044b76d3dc 100644 --- a/crypto/tls/key_agreement.go +++ b/crypto/tls/key_agreement.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "slices" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdh" @@ -42,9 +43,8 @@ var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") // rsaKeyAgreement implements the standard TLS key agreement where the client // encrypts the pre-master secret to the server's public key. type rsaKeyAgreement struct { - version uint16 - privateKey *rsa.PrivateKey - verifyError error + privateKey *rsa.PrivateKey // nil if the server doesn't use RSA key agreement + publicKey *rsa.PublicKey // nil if the client doesn't use RSA key agreement } func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { @@ -65,16 +65,15 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi if !ok { return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") } + if ka.privateKey, ok = priv.(*rsa.PrivateKey); ok { + ka.publicKey = &ka.privateKey.PublicKey + } + // Perform constant time RSA PKCS #1 v1.5 decryption preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) if err != nil { return nil, err } - - // zcrypto - ka.privateKey = cert.PrivateKey.(*rsa.PrivateKey) - ka.version = version - // We don't check the version number in the premaster secret. For one, // by checking it, we would leak information about the validity of the // encrypted pre-master secret. Secondly, it provides only a small @@ -161,27 +160,6 @@ func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint1 return md5SHA1Hash(slices) } -// keyAgreementAuthentication is a helper interface that specifies how -// to authenticate the ServerKeyExchange parameters. -type keyAgreementAuthentication interface { - signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) - verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) ([]byte, error) -} - -// nilKeyAgreementAuthentication does not authenticate the key -// agreement parameters. -type nilKeyAgreementAuthentication struct{} - -func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) { - skx := new(serverKeyExchangeMsg) - skx.key = params - return skx, nil -} - -func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) ([]byte, error) { - return nil, nil -} - // ecdheKeyAgreement implements a TLS key agreement where the server // generates an ephemeral EC public/private key pair and signs it. The // pre-master secret is then calculated using ECDH. The signature may @@ -196,68 +174,62 @@ type ecdheKeyAgreement struct { ckx *clientKeyExchangeMsg preMasterSecret []byte - // zcrypto - verifyError error - curveID uint16 - pub []byte + // curveID and signatureAlgorithm are set by processServerKeyExchange and + // generateServerKeyExchange. + curveID CurveID + signatureAlgorithm SignatureScheme } func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { - var curveID CurveID for _, c := range clientHello.supportedCurves { if config.supportsCurve(ka.version, c) { - curveID = c + ka.curveID = c break } } - if curveID == 0 { + if ka.curveID == 0 { return nil, errors.New("tls: no supported elliptic curves offered") } - - // zcrypto - ka.curveID = uint16(curveID) - - if _, ok := curveForCurveID(curveID); !ok { + if _, ok := curveForCurveID(ka.curveID); !ok { return nil, errors.New("tls: CurvePreferences includes unsupported curve") } - key, err := generateECDHEKey(config.rand(), curveID) + key, err := generateECDHEKey(config.rand(), ka.curveID) if err != nil { return nil, err } + ka.key = key // See RFC 4492, Section 5.4. ecdhePublic := key.PublicKey().Bytes() serverECDHEParams := make([]byte, 1+2+1+len(ecdhePublic)) serverECDHEParams[0] = 3 // named curve - serverECDHEParams[1] = byte(curveID >> 8) - serverECDHEParams[2] = byte(curveID) + serverECDHEParams[1] = byte(ka.curveID >> 8) + serverECDHEParams[2] = byte(ka.curveID) serverECDHEParams[3] = byte(len(ecdhePublic)) copy(serverECDHEParams[4:], ecdhePublic) - ka.key = key - - // zcrypto - ka.pub = ecdhePublic - priv, ok := cert.PrivateKey.(crypto.Signer) if !ok { return nil, fmt.Errorf("tls: certificate private key of type %T does not implement crypto.Signer", cert.PrivateKey) } - var signatureAlgorithm SignatureScheme var sigType uint8 var sigHash crypto.Hash if ka.version >= VersionTLS12 { - signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms) + ka.signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms) if err != nil { return nil, err } - sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) + sigType, sigHash, err = typeAndHashFromSignatureScheme(ka.signatureAlgorithm) if err != nil { return nil, err } + if sigHash == crypto.SHA1 { + tlssha1.Value() // ensure godebug is initialized + tlssha1.IncNonDefault() + } } else { sigType, sigHash, err = legacyTypeAndHashFromPublicKey(priv.Public()) if err != nil { @@ -288,8 +260,8 @@ func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Cer copy(skx.key, serverECDHEParams) k := skx.key[len(serverECDHEParams):] if ka.version >= VersionTLS12 { - k[0] = byte(signatureAlgorithm >> 8) - k[1] = byte(signatureAlgorithm) + k[0] = byte(ka.signatureAlgorithm >> 8) + k[1] = byte(ka.signatureAlgorithm) k = k[2:] } k[0] = byte(len(sig) >> 8) @@ -323,7 +295,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell if skx.key[0] != 3 { // named curve return errors.New("tls: server selected unsupported curve") } - curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) + ka.curveID = CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) publicLen := int(skx.key[3]) if publicLen+4 > len(skx.key) { @@ -337,11 +309,15 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell return errServerKeyExchange } - if _, ok := curveForCurveID(curveID); !ok { + if !slices.Contains(clientHello.supportedCurves, ka.curveID) { + return errors.New("tls: server selected unoffered curve") + } + + if _, ok := curveForCurveID(ka.curveID); !ok { return errors.New("tls: server selected unsupported curve") } - key, err := generateECDHEKey(config.rand(), curveID) + key, err := generateECDHEKey(config.rand(), ka.curveID) if err != nil { return err } @@ -365,18 +341,23 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell var sigType uint8 var sigHash crypto.Hash if ka.version >= VersionTLS12 { - signatureAlgorithm := SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) + ka.signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) sig = sig[2:] if len(sig) < 2 { return errServerKeyExchange } - if !isSupportedSignatureAlgorithm(signatureAlgorithm, clientHello.supportedSignatureAlgorithms) { + + if !isSupportedSignatureAlgorithm(ka.signatureAlgorithm, clientHello.supportedSignatureAlgorithms) { return errors.New("tls: certificate used with invalid signature algorithm") } - sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) + sigType, sigHash, err = typeAndHashFromSignatureScheme(ka.signatureAlgorithm) if err != nil { return err } + if sigHash == crypto.SHA1 { + tlssha1.Value() // ensure godebug is initialized + tlssha1.IncNonDefault() + } } else { sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey) if err != nil { diff --git a/crypto/tls/key_schedule.go b/crypto/tls/key_schedule.go index 111067ecae0..906071c6a20 100644 --- a/crypto/tls/key_schedule.go +++ b/crypto/tls/key_schedule.go @@ -6,94 +6,29 @@ package tls import ( "errors" - "fmt" - "github.com/runZeroInc/excrypto/crypto/ecdh" - "github.com/runZeroInc/excrypto/crypto/hmac" - "github.com/runZeroInc/excrypto/crypto/internal/mlkem768" - "hash" "io" - "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" - "github.com/runZeroInc/excrypto/x/crypto/hkdf" - "github.com/runZeroInc/excrypto/x/crypto/sha3" + "github.com/runZeroInc/excrypto/hash" + + "github.com/runZeroInc/excrypto/crypto/ecdh" + "github.com/runZeroInc/excrypto/crypto/hmac" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/mlkem" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls13" ) // This file contains the functions necessary to compute the TLS 1.3 key // schedule. See RFC 8446, Section 7. -const ( - resumptionBinderLabel = "res binder" - clientEarlyTrafficLabel = "c e traffic" - clientHandshakeTrafficLabel = "c hs traffic" - serverHandshakeTrafficLabel = "s hs traffic" - clientApplicationTrafficLabel = "c ap traffic" - serverApplicationTrafficLabel = "s ap traffic" - exporterLabel = "exp master" - resumptionLabel = "res master" - trafficUpdateLabel = "traffic upd" -) - -// expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. -func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte { - var hkdfLabel cryptobyte.Builder - hkdfLabel.AddUint16(uint16(length)) - hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes([]byte("tls13 ")) - b.AddBytes([]byte(label)) - }) - hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(context) - }) - hkdfLabelBytes, err := hkdfLabel.Bytes() - if err != nil { - // Rather than calling BytesOrPanic, we explicitly handle this error, in - // order to provide a reasonable error message. It should be basically - // impossible for this to panic, and routing errors back through the - // tree rooted in this function is quite painful. The labels are fixed - // size, and the context is either a fixed-length computed hash, or - // parsed from a field which has the same length limitation. As such, an - // error here is likely to only be caused during development. - // - // NOTE: another reasonable approach here might be to return a - // randomized slice if we encounter an error, which would break the - // connection, but avoid panicking. This would perhaps be safer but - // significantly more confusing to users. - panic(fmt.Errorf("failed to construct HKDF label: %s", err)) - } - out := make([]byte, length) - n, err := hkdf.Expand(c.hash.New, secret, hkdfLabelBytes).Read(out) - if err != nil || n != length { - panic("tls: HKDF-Expand-Label invocation failed unexpectedly") - } - return out -} - -// deriveSecret implements Derive-Secret from RFC 8446, Section 7.1. -func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte { - if transcript == nil { - transcript = c.hash.New() - } - return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size()) -} - -// extract implements HKDF-Extract with the cipher suite hash. -func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { - if newSecret == nil { - newSecret = make([]byte, c.hash.Size()) - } - return hkdf.Extract(c.hash.New, newSecret, currentSecret) -} - // nextTrafficSecret generates the next traffic secret, given the current one, // according to RFC 8446, Section 7.2. func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte { - return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size()) + return tls13.ExpandLabel(c.hash.New, trafficSecret, "traffic upd", nil, c.hash.Size()) } // trafficKey generates traffic keys according to RFC 8446, Section 7.3. func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { - key = c.expandLabel(trafficSecret, "key", nil, c.keyLen) - iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength) + key = tls13.ExpandLabel(c.hash.New, trafficSecret, "key", nil, c.keyLen) + iv = tls13.ExpandLabel(c.hash.New, trafficSecret, "iv", nil, aeadNonceLength) return } @@ -101,7 +36,7 @@ func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { // to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey // selection. func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte { - finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size()) + finishedKey := tls13.ExpandLabel(c.hash.New, baseKey, "finished", nil, c.hash.Size()) verifyData := hmac.New(c.hash.New, finishedKey) verifyData.Write(transcript.Sum(nil)) return verifyData.Sum(nil) @@ -109,51 +44,17 @@ func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) [] // exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to // RFC 8446, Section 7.5. -func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { - expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript) +func (c *cipherSuiteTLS13) exportKeyingMaterial(s *tls13.MasterSecret, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { + expMasterSecret := s.ExporterMasterSecret(transcript) return func(label string, context []byte, length int) ([]byte, error) { - secret := c.deriveSecret(expMasterSecret, label, nil) - h := c.hash.New() - h.Write(context) - return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil + return expMasterSecret.Exporter(label, context, length), nil } } type keySharePrivateKeys struct { curveID CurveID ecdhe *ecdh.PrivateKey - kyber *mlkem768.DecapsulationKey -} - -// kyberDecapsulate implements decapsulation according to Kyber Round 3. -func kyberDecapsulate(dk *mlkem768.DecapsulationKey, c []byte) ([]byte, error) { - K, err := mlkem768.Decapsulate(dk, c) - if err != nil { - return nil, err - } - return kyberSharedSecret(K, c), nil -} - -// kyberEncapsulate implements encapsulation according to Kyber Round 3. -func kyberEncapsulate(ek []byte) (c, ss []byte, err error) { - c, ss, err = mlkem768.Encapsulate(ek) - if err != nil { - return nil, nil, err - } - return c, kyberSharedSecret(ss, c), nil -} - -func kyberSharedSecret(K, c []byte) []byte { - // Package mlkem768 implements ML-KEM, which compared to Kyber removed a - // final hashing step. Compute SHAKE-256(K || SHA3-256(c), 32) to match Kyber. - // See https://words.filippo.io/mlkem768/#bonus-track-using-a-ml-kem-implementation-as-kyber-v3. - h := sha3.NewShake256() - h.Write(K) - ch := sha3.Sum256(c) - h.Write(ch[:]) - out := make([]byte, 32) - h.Read(out) - return out + mlkem *mlkem.DecapsulationKey768 } const x25519PublicKeySize = 32 diff --git a/crypto/tls/key_schedule_test.go b/crypto/tls/key_schedule_test.go index 86daf303866..b23d4b8ad85 100644 --- a/crypto/tls/key_schedule_test.go +++ b/crypto/tls/key_schedule_test.go @@ -7,13 +7,80 @@ package tls import ( "bytes" "encoding/hex" - "github.com/runZeroInc/excrypto/crypto/internal/mlkem768" - "hash" "strings" "testing" "unicode" + + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls13" + "github.com/runZeroInc/excrypto/crypto/sha256" ) +func TestACVPVectors(t *testing.T) { + // https://github.com/usnistgov/ACVP-Server/blob/3a7333f63/gen-val/json-files/TLS-v1.3-KDF-RFC8446/prompt.json#L428-L436 + psk := fromHex("56288B726C73829F7A3E47B103837C8139ACF552E7530C7A710B35ED41191698") + dhe := fromHex("EFFE9EC26AA29FD750DFA6A10B944D74071595B27EE88887D5E11C84590B5CC3") + helloClientRandom := fromHex("E9137679E582BA7C1DB41CF725F86C6D09C8C05F297BAD9A65B552EAF524FDE4") + helloServerRandom := fromHex("23ECCFD030790748C8F8D8A656FD98D717F1B62AF3712F97211D2070B499F98A") + finishedClientRandom := fromHex("62A62FA75563ED4FDCAA0BC16567B314871C304ACF06B0FFC3F08C1797594D43") + finishedServerRandom := fromHex("C750EDA6696CD101B142BD79E00E6AC8C5F2C0ABC78DD64F4D991326659E9299") + + // https://github.com/usnistgov/ACVP-Server/blob/3a7333f63/gen-val/json-files/TLS-v1.3-KDF-RFC8446/expectedResults.json#L571-L581 + clientEarlyTrafficSecret := fromHex("3272189698C3594D18F58EFA3F12B638A249515099BE7A2FA9836BABE74F0111") + earlyExporterMasterSecret := fromHex("88E078F562CDC930219F6A5E98A1CE8C6E5F3DAC5AC516459A96F2EF8F114C66") + clientHandshakeTrafficSecret := fromHex("B32306C3CE9932C460A1FE6C0F060593974842036B96FA45049B7352E71C2AD2") + serverHandshakeTrafficSecret := fromHex("22787F8CA269D34BC549AC8BA19F2040938A3AA370D7CC9D60F720882B88D01B") + clientApplicationTrafficSecret := fromHex("47D7EA08397B5871154B0FE85584BCC30A87C69E84D69B56007C5B21F76493BA") + serverApplicationTrafficSecret := fromHex("EFBDB0C873C0480DA57307083839A8984BE25B9A8545E4FCA029940FE2800565") + exporterMasterSecret := fromHex("8A43D787EE3804EAD4A2A5B32972F9896B696295645D7222E1FD081DDD939834") + resumptionMasterSecret := fromHex("5F4C961329C91044011ACBECB0B289282E0E3FED045CB3EA924DFFE5FE654B3D") + + // The "Random" values are undocumented, but they are meant to be written to + // the hash in sequence to develop the transcript. + transcript := sha256.New() + + es := tls13.NewEarlySecret(sha256.New, psk) + + transcript.Write(helloClientRandom) + + if got := es.ClientEarlyTrafficSecret(transcript); !bytes.Equal(got, clientEarlyTrafficSecret) { + t.Errorf("clientEarlyTrafficSecret = %x, want %x", got, clientEarlyTrafficSecret) + } + if got := tls13.TestingOnlyExporterSecret(es.EarlyExporterMasterSecret(transcript)); !bytes.Equal(got, earlyExporterMasterSecret) { + t.Errorf("earlyExporterMasterSecret = %x, want %x", got, earlyExporterMasterSecret) + } + + hs := es.HandshakeSecret(dhe) + + transcript.Write(helloServerRandom) + + if got := hs.ClientHandshakeTrafficSecret(transcript); !bytes.Equal(got, clientHandshakeTrafficSecret) { + t.Errorf("clientHandshakeTrafficSecret = %x, want %x", got, clientHandshakeTrafficSecret) + } + if got := hs.ServerHandshakeTrafficSecret(transcript); !bytes.Equal(got, serverHandshakeTrafficSecret) { + t.Errorf("serverHandshakeTrafficSecret = %x, want %x", got, serverHandshakeTrafficSecret) + } + + ms := hs.MasterSecret() + + transcript.Write(finishedServerRandom) + + if got := ms.ClientApplicationTrafficSecret(transcript); !bytes.Equal(got, clientApplicationTrafficSecret) { + t.Errorf("clientApplicationTrafficSecret = %x, want %x", got, clientApplicationTrafficSecret) + } + if got := ms.ServerApplicationTrafficSecret(transcript); !bytes.Equal(got, serverApplicationTrafficSecret) { + t.Errorf("serverApplicationTrafficSecret = %x, want %x", got, serverApplicationTrafficSecret) + } + if got := tls13.TestingOnlyExporterSecret(ms.ExporterMasterSecret(transcript)); !bytes.Equal(got, exporterMasterSecret) { + t.Errorf("exporterMasterSecret = %x, want %x", got, exporterMasterSecret) + } + + transcript.Write(finishedClientRandom) + + if got := ms.ResumptionMasterSecret(transcript); !bytes.Equal(got, resumptionMasterSecret) { + t.Errorf("resumptionMasterSecret = %x, want %x", got, resumptionMasterSecret) + } +} + // This file contains tests derived from draft-ietf-tls-tls13-vectors-07. func parseVector(v string) []byte { @@ -32,78 +99,6 @@ func parseVector(v string) []byte { return res } -func TestDeriveSecret(t *testing.T) { - chTranscript := cipherSuitesTLS13[0].hash.New() - chTranscript.Write(parseVector(` - payload (512 octets): 01 00 01 fc 03 03 1b c3 ce b6 bb e3 9c ff - 93 83 55 b5 a5 0a db 6d b2 1b 7a 6a f6 49 d7 b4 bc 41 9d 78 76 - 48 7d 95 00 00 06 13 01 13 03 13 02 01 00 01 cd 00 00 00 0b 00 - 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00 12 - 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 33 00 - 26 00 24 00 1d 00 20 e4 ff b6 8a c0 5f 8d 96 c9 9d a2 66 98 34 - 6c 6b e1 64 82 ba dd da fe 05 1a 66 b4 f1 8d 66 8f 0b 00 2a 00 - 00 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 02 - 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06 02 - 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01 00 15 00 57 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 29 00 dd 00 b8 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00 - 00 00 00 26 2a 64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70 - ad 3c 49 88 83 c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 - 82 11 72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6 - 1d 28 27 db 27 9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0 - 37 25 a6 a4 da fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 - 90 6c 5b 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5 - ae a6 17 64 6f ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d - e6 50 5e 5b fb c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 fa d6 aa - cb 00 21 20 3a dd 4f b2 d8 fd f8 22 a0 ca 3c f7 67 8e f5 e8 8d - ae 99 01 41 c5 92 4d 57 bb 6f a3 1b 9e 5f 9d`)) - - type args struct { - secret []byte - label string - transcript hash.Hash - } - tests := []struct { - name string - args args - want []byte - }{ - { - `derive secret for handshake "tls13 derived"`, - args{ - parseVector(`PRK (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2 - 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`), - "derived", - nil, - }, - parseVector(`expanded (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba - b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`), - }, - { - `derive secret "tls13 c e traffic"`, - args{ - parseVector(`PRK (32 octets): 9b 21 88 e9 b2 fc 6d 64 d7 1d c3 29 90 0e 20 bb - 41 91 50 00 f6 78 aa 83 9c bb 79 7c b7 d8 33 2c`), - "c e traffic", - chTranscript, - }, - parseVector(`expanded (32 octets): 3f bb e6 a6 0d eb 66 c3 0a 32 79 5a ba 0e - ff 7e aa 10 10 55 86 e7 be 5c 09 67 8d 63 b6 ca ab 62`), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := cipherSuitesTLS13[0] - if got := c.deriveSecret(tt.args.secret, tt.args.label, tt.args.transcript); !bytes.Equal(got, tt.want) { - t.Errorf("cipherSuiteTLS13.deriveSecret() = % x, want % x", got, tt.want) - } - }) - } -} - func TestTrafficKey(t *testing.T) { trafficSecret := parseVector( `PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4 @@ -123,90 +118,3 @@ func TestTrafficKey(t *testing.T) { t.Errorf("cipherSuiteTLS13.trafficKey() gotIV = % x, want % x", gotIV, wantIV) } } - -func TestExtract(t *testing.T) { - type args struct { - newSecret []byte - currentSecret []byte - } - tests := []struct { - name string - args args - want []byte - }{ - { - `extract secret "early"`, - args{ - nil, - nil, - }, - parseVector(`secret (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c - e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`), - }, - { - `extract secret "master"`, - args{ - nil, - parseVector(`salt (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5 - 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4`), - }, - parseVector(`secret (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a - 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19`), - }, - { - `extract secret "handshake"`, - args{ - parseVector(`IKM (32 octets): 8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d - 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d`), - parseVector(`salt (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97 - 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`), - }, - parseVector(`secret (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b - 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac`), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := cipherSuitesTLS13[0] - if got := c.extract(tt.args.newSecret, tt.args.currentSecret); !bytes.Equal(got, tt.want) { - t.Errorf("cipherSuiteTLS13.extract() = % x, want % x", got, tt.want) - } - }) - } -} - -func TestKyberDecapsulate(t *testing.T) { - // From https://pq-crystals.org/kyber/data/kyber-submission-nist-round3.zip - dkBytes, _ := hex.DecodeString("07638FB69868F3D320E5862BD96933FEB311B362093C9B5D50170BCED43F1B536D9A204BB1F22695950BA1F2A9E8EB828B284488760B3FC84FABA04275D5628E39C5B2471374283C503299C0AB49B66B8BBB56A4186624F919A2BA59BB08D8551880C2BEFC4F87F25F59AB587A79C327D792D54C974A69262FF8A78938289E9A87B688B083E0595FE218B6BB1505941CE2E81A5A64C5AAC60417256985349EE47A52420A5F97477B7236AC76BC70E8288729287EE3E34A3DBC3683C0B7B10029FC203418537E7466BA6385A8FF301EE12708F82AAA1E380FC7A88F8F205AB7E88D7E95952A55BA20D09B79A47141D62BF6EB7DD307B08ECA13A5BC5F6B68581C6865B27BBCDDAB142F4B2CBFF488C8A22705FAA98A2B9EEA3530C76662335CC7EA3A00777725EBCCCD2A4636B2D9122FF3AB77123CE0883C1911115E50C9E8A94194E48DD0D09CFFB3ADCD2C1E92430903D07ADBF00532031575AA7F9E7B5A1F3362DEC936D4043C05F2476C07578BC9CBAF2AB4E382727AD41686A96B2548820BB03B32F11B2811AD62F489E951632ABA0D1DF89680CC8A8B53B481D92A68D70B4EA1C3A6A561C0692882B5CA8CC942A8D495AFCB06DE89498FB935B775908FE7A03E324D54CC19D4E1AABD3593B38B19EE1388FE492B43127E5A504253786A0D69AD32601C28E2C88504A5BA599706023A61363E17C6B9BB59BDC697452CD059451983D738CA3FD034E3F5988854CA05031DB09611498988197C6B30D258DFE26265541C89A4B31D6864E9389B03CB74F7EC4323FB9421A4B9790A26D17B0398A26767350909F84D57B6694DF830664CA8B3C3C03ED2AE67B89006868A68527CCD666459AB7F056671000C6164D3A7F266A14D97CBD7004D6C92CACA770B844A4FA9B182E7B18CA885082AC5646FCB4A14E1685FEB0C9CE3372AB95365C04FD83084F80A23FF10A05BF15F7FA5ACC6C0CB462C33CA524FA6B8BB359043BA68609EAA2536E81D08463B19653B5435BA946C9ADDEB202B04B031CC960DCC12E4518D428B32B257A4FC7313D3A7980D80082E934F9D95C32B0A0191A23604384DD9E079BBBAA266D14C3F756B9F2133107433A4E83FA7187282A809203A4FAF841851833D121AC383843A5E55BC2381425E16C7DB4CC9AB5C1B0D91A47E2B8DE0E582C86B6B0D907BB360B97F40AB5D038F6B75C814B27D9B968D419832BC8C2BEE605EF6E5059D33100D90485D378450014221736C07407CAC260408AA64926619788B8601C2A752D1A6CBF820D7C7A04716203225B3895B9342D147A8185CFC1BB65BA06B4142339903C0AC4651385B45D98A8B19D28CD6BAB088787F7EE1B12461766B43CBCCB96434427D93C065550688F6948ED1B5475A425F1B85209D061C08B56C1CC069F6C0A7C6F29358CAB911087732A649D27C9B98F9A48879387D9B00C25959A71654D6F6A946164513E47A75D005986C2363C09F6B537ECA78B9303A5FA457608A586A653A347DB04DFCC19175B3A301172536062A658A95277570C8852CA8973F4AE123A334047DD711C8927A634A03388A527B034BF7A8170FA702C1F7C23EC32D18A2374890BE9C787A9409C82D192C4BB705A2F996CE405DA72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922D4EC143B50F01423B177895EDEE22BB739F647ECF85F50BC25EF7B5A725DEE868626ED79D451140800E03B59B956F8210E556067407D13DC90FA9E8B872BFB8F") - dk, err := mlkem768.NewKeyFromExtendedEncoding(dkBytes) - if err != nil { - t.Fatal(err) - } - ct, _ := hex.DecodeString("B52C56B92A4B7CE9E4CB7C5B1B163167A8A1675B2FDEF84A5B67CA15DB694C9F11BD027C30AE22EC921A1D911599AF0585E48D20DA70DF9F39E32EF95D4C8F44BFEFDAA5DA64F1054631D04D6D3CFD0A540DD7BA3886E4B5F13E878788604C95C096EAB3919F427521419A946C26CC041475D7124CDC01D0373E5B09C7A70603CFDB4FB3405023F2264DC3F983C4FC02A2D1B268F2208A1F6E2A6209BFF12F6F465F0B069C3A7F84F606D8A94064003D6EC114C8E808D3053884C1D5A142FBF20112EB360FDA3F0F28B172AE50F5E7D83801FB3F0064B687187074BD7FE30EDDAA334CF8FC04FA8CED899CEADE4B4F28B68372BAF98FF482A415B731155B75CEB976BE0EA0285BA01A27F1857A8FB377A3AE0C23B2AA9A079BFABFF0D5B2F1CD9B718BEA03C42F343A39B4F142D01AD8ACBB50E38853CF9A50C8B44C3CF671A4A9043B26DDBB24959AD6715C08521855C79A23B9C3D6471749C40725BDD5C2776D43AED20204BAA141EFB3304917474B7F9F7A4B08B1A93DAED98C67495359D37D67F7438BEE5E43585634B26C6B3810D7CDCBC0F6EB877A6087E68ACB8480D3A8CF6900447E49B417F15A53B607A0E216B855970D37406870B4568722DA77A4084703816784E2F16BED18996532C5D8B7F5D214464E5F3F6E905867B0CE119E252A66713253544685D208E1723908A0CE97834652E08AE7BDC881A131B73C71E84D20D68FDEFF4F5D70CD1AF57B78E3491A9865942321800A203C05ED1FEEB5A28E584E19F6535E7F84E4A24F84A72DCAF5648B4A4235DD664464482F03176E888C28BFC6C1CB238CFFA35A321E71791D9EA8ED0878C61121BF8D2A4AB2C1A5E120BC40ABB1892D1715090A0EE48252CA297A99AA0E510CF26B1ADD06CA543E1C5D6BDCD3B9C585C8538045DB5C252EC3C8C3C954D9BE5907094A894E60EAB43538CFEE82E8FFC0791B0D0F43AC1627830A61D56DAD96C62958B0DE780B78BD47A604550DAB83FFF227C324049471F35248CFB849B25724FF704D5277AA352D550958BE3B237DFF473EC2ADBAEA48CA2658AEFCC77BBD4264AB374D70EAE5B964416CE8226A7E3255A0F8D7E2ADCA062BCD6D78D60D1B32E11405BE54B66EF0FDDD567702A3BCCFEDE3C584701269ED14809F06F8968356BB9267FE86E514252E88BB5C30A7ECB3D0E621021EE0FBF7871B09342BF84F55C97EAF86C48189C7FF4DF389F077E2806E5FA73B3E9458A16C7E275F4F602275580EB7B7135FB537FA0CD95D6EA58C108CD8943D70C1643111F4F01CA8A8276A902666ED81B78D168B006F16AAA3D8E4CE4F4D0FB0997E41AEFFB5B3DAA838732F357349447F387776C793C0479DE9E99498CC356FDB0075A703F23C55D47B550EC89B02ADE89329086A50843456FEDC3788AC8D97233C54560467EE1D0F024B18428F0D73B30E19F5C63B9ABF11415BEA4D0170130BAABD33C05E6524E5FB5581B22B0433342248266D0F1053B245CC2462DC44D34965102482A8ED9E4E964D5683E5D45D0C8269") - ss, err := kyberDecapsulate(dk, ct) - if err != nil { - t.Fatal(err) - } - exp, _ := hex.DecodeString("914CB67FE5C38E73BF74181C0AC50428DEDF7750A98058F7D536708774535B29") - if !bytes.Equal(ss, exp) { - t.Fatalf("got %x, want %x", ss, exp) - } -} - -func TestKyberEncapsulate(t *testing.T) { - dk, err := mlkem768.GenerateKey() - if err != nil { - t.Fatal(err) - } - ct, ss, err := kyberEncapsulate(dk.EncapsulationKey()) - if err != nil { - t.Fatal(err) - } - dkSS, err := kyberDecapsulate(dk, ct) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(ss, dkSS) { - t.Fatalf("got %x, want %x", ss, dkSS) - } -} diff --git a/crypto/tls/link_test.go b/crypto/tls/link_test.go new file mode 100644 index 00000000000..b635a72e662 --- /dev/null +++ b/crypto/tls/link_test.go @@ -0,0 +1,108 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/runZeroInc/excrypto/internal/testenv" +) + +// Tests that the linker is able to remove references to the Client or Server if unused. +func TestLinkerGC(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + t.Parallel() + goBin := testenv.GoToolPath(t) + testenv.MustHaveGoBuild(t) + + tests := []struct { + name string + program string + want []string + bad []string + }{ + { + name: "empty_import", + program: `package main +import _ "crypto/tls" +func main() {} +`, + bad: []string{ + "tls.(*Conn)", + "type:crypto/tls.clientHandshakeState", + "type:crypto/tls.serverHandshakeState", + }, + }, + { + name: "client_and_server", + program: `package main +import "crypto/tls" +func main() { + tls.Dial("", "", nil) + tls.Server(nil, nil) +} +`, + want: []string{ + "crypto/tls.(*Conn).clientHandshake", + "crypto/tls.(*Conn).serverHandshake", + }, + }, + { + name: "only_client", + program: `package main +import "crypto/tls" +func main() { tls.Dial("", "", nil) } +`, + want: []string{ + "crypto/tls.(*Conn).clientHandshake", + }, + bad: []string{ + "crypto/tls.(*Conn).serverHandshake", + }, + }, + // TODO: add only_server like func main() { tls.Server(nil, nil) } + // That currently brings in the client via Conn.handleRenegotiation. + + } + tmpDir := t.TempDir() + goFile := filepath.Join(tmpDir, "x.go") + exeFile := filepath.Join(tmpDir, "x.exe") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil { + t.Fatal(err) + } + os.Remove(exeFile) + cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go") + cmd.Dir = tmpDir + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("compile: %v, %s", err, out) + } + + cmd = exec.Command(goBin, "tool", "nm", "x.exe") + cmd.Dir = tmpDir + nm, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("nm: %v, %s", err, nm) + } + for _, sym := range tt.want { + if !bytes.Contains(nm, []byte(sym)) { + t.Errorf("expected symbol %q not found", sym) + } + } + for _, sym := range tt.bad { + if bytes.Contains(nm, []byte(sym)) { + t.Errorf("unexpected symbol %q found", sym) + } + } + }) + } +} diff --git a/crypto/tls/prf.go b/crypto/tls/prf.go index a6bc92335ba..a2c6cc5eca5 100644 --- a/crypto/tls/prf.go +++ b/crypto/tls/prf.go @@ -7,16 +7,20 @@ package tls import ( "errors" "fmt" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/hmac" + "github.com/runZeroInc/excrypto/crypto/internal/fips140/tls12" "github.com/runZeroInc/excrypto/crypto/md5" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/sha512" ) +type prfFunc func(secret []byte, label string, seed []byte, keyLen int) []byte + // Split a premaster secret in two as specified in RFC 4346, Section 5. func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { s1 = secret[0 : (len(secret)+1)/2] @@ -46,7 +50,8 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { } // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. -func prf10(result, secret, label, seed []byte) { +func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { + result := make([]byte, keyLen) hashSHA1 := sha1.New hashMD5 := md5.New @@ -62,16 +67,14 @@ func prf10(result, secret, label, seed []byte) { for i, b := range result2 { result[i] ^= b } + + return result } // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. -func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { - return func(result, secret, label, seed []byte) { - labelAndSeed := make([]byte, len(label)+len(seed)) - copy(labelAndSeed, label) - copy(labelAndSeed[len(label):], seed) - - pHash(result, secret, labelAndSeed, hashFunc) +func prf12(hashFunc func() hash.Hash) prfFunc { + return func(secret []byte, label string, seed []byte, keyLen int) []byte { + return tls12.PRF(hashFunc, secret, label, seed, keyLen) } } @@ -80,13 +83,13 @@ const ( finishedVerifyLength = 12 // Length of verify_data in a Finished message. ) -var masterSecretLabel = []byte("master secret") -var extendedMasterSecretLabel = []byte("extended master secret") -var keyExpansionLabel = []byte("key expansion") -var clientFinishedLabel = []byte("client finished") -var serverFinishedLabel = []byte("server finished") +const masterSecretLabel = "master secret" +const extendedMasterSecretLabel = "extended master secret" +const keyExpansionLabel = "key expansion" +const clientFinishedLabel = "client finished" +const serverFinishedLabel = "server finished" -func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { +func prfAndHashForVersion(version uint16, suite *cipherSuite) (prfFunc, crypto.Hash) { switch version { case VersionTLS10, VersionTLS11: return prf10, crypto.Hash(0) @@ -100,7 +103,7 @@ func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secr } } -func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { +func prfForVersion(version uint16, suite *cipherSuite) prfFunc { prf, _ := prfAndHashForVersion(version, suite) return prf } @@ -112,17 +115,19 @@ func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecr seed = append(seed, clientRandom...) seed = append(seed, serverRandom...) - masterSecret := make([]byte, masterSecretLength) - prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) - return masterSecret + return prfForVersion(version, suite)(preMasterSecret, masterSecretLabel, seed, masterSecretLength) } // extMasterFromPreMasterSecret generates the extended master secret from the // pre-master secret. See RFC 7627. func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) []byte { - masterSecret := make([]byte, masterSecretLength) - prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, transcript) - return masterSecret + prf, hash := prfAndHashForVersion(version, suite) + if version == VersionTLS12 { + // Use the FIPS 140-3 module only for TLS 1.2 with EMS, which is the + // only TLS 1.0-1.2 approved mode per IG D.Q. + return tls12.MasterSecret(hash.New, preMasterSecret, transcript) + } + return prf(preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength) } // keysFromMasterSecret generates the connection keys from the master @@ -134,8 +139,7 @@ func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clie seed = append(seed, clientRandom...) n := 2*macLen + 2*keyLen + 2*ivLen - keyMaterial := make([]byte, n) - prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) + keyMaterial := prfForVersion(version, suite)(masterSecret, keyExpansionLabel, seed, n) clientMAC = keyMaterial[:macLen] keyMaterial = keyMaterial[macLen:] serverMAC = keyMaterial[:macLen] @@ -178,7 +182,7 @@ type finishedHash struct { buffer []byte version uint16 - prf func(result, secret, label, seed []byte) + prf prfFunc } func (h *finishedHash) Write(msg []byte) (n int, err error) { @@ -210,17 +214,13 @@ func (h finishedHash) Sum() []byte { // clientSum returns the contents of the verify_data member of a client's // Finished message. func (h finishedHash) clientSum(masterSecret []byte) []byte { - out := make([]byte, finishedVerifyLength) - h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) - return out + return h.prf(masterSecret, clientFinishedLabel, h.Sum(), finishedVerifyLength) } // serverSum returns the contents of the verify_data member of a server's // Finished message. func (h finishedHash) serverSum(masterSecret []byte) []byte { - out := make([]byte, finishedVerifyLength) - h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) - return out + return h.prf(masterSecret, serverFinishedLabel, h.Sum(), finishedVerifyLength) } // hashForClientCertificate returns the handshake messages so far, pre-hashed if @@ -293,8 +293,6 @@ func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clien seed = append(seed, context...) } - keyMaterial := make([]byte, length) - prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) - return keyMaterial, nil + return prfForVersion(version, suite)(masterSecret, label, seed, length), nil } } diff --git a/crypto/tls/quic_test.go b/crypto/tls/quic_test.go index 1bb2e55bddc..51cd4ef765d 100644 --- a/crypto/tls/quic_test.go +++ b/crypto/tls/quic_test.go @@ -9,6 +9,7 @@ import ( "context" "errors" "reflect" + "strings" "testing" ) @@ -278,7 +279,7 @@ func TestQUICPostHandshakeClientAuthentication(t *testing.T) { certReq := new(certificateRequestMsgTLS13) certReq.ocspStapling = true certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS13) certReqBytes, err := certReq.marshal() if err != nil { t.Fatal(err) @@ -308,11 +309,11 @@ func TestQUICPostHandshakeKeyUpdate(t *testing.T) { if err != nil { t.Fatal(err) } - if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{ - byte(typeKeyUpdate), - byte(0), byte(0), byte(len(keyUpdateBytes)), - }, keyUpdateBytes...)); !errors.Is(err, alertUnexpectedMessage) { - t.Fatalf("key update request: got error %v, want alertUnexpectedMessage", err) + expectedErr := "unexpected key update message" + if err = cli.conn.HandleData(QUICEncryptionLevelApplication, keyUpdateBytes); err == nil { + t.Fatalf("key update request: expected error from post-handshake key update, got nil") + } else if !strings.Contains(err.Error(), expectedErr) { + t.Fatalf("key update request: got error %v, expected substring %q", err, expectedErr) } } diff --git a/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA index a35aa57ee09..3bd86fd90ed 100644 --- a/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA +++ b/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 60 8a bf 2b 6f |....]...Y..`..+o| -00000010 c1 f0 f3 7b d4 78 2c d9 15 3f 33 6a 4b 96 aa 83 |...{.x,..?3jK...| -00000020 54 ae 66 8f 0f e7 b1 68 31 00 39 20 d8 4d f2 2c |T.f....h1.9 .M.,| -00000030 8b 85 98 d6 af e0 07 98 d5 cb 89 72 fb 8d c0 73 |...........r...s| -00000040 cc 68 cf 58 21 4a 8a fc c3 8e 90 0a c0 09 00 00 |.h.X!J..........| +00000000 16 03 01 00 5d 02 00 00 59 03 01 1a 76 c4 d5 b5 |....]...Y...v...| +00000010 7e 30 1c 1e c3 62 8b 92 a8 19 9b 62 4e 36 a1 d3 |~0...b.....bN6..| +00000020 c8 e3 55 f6 64 5f 06 aa 19 9a 48 20 24 a4 2d a9 |..U.d_....H $.-.| +00000030 8a bd cf 4e 9b cf 7d c7 8e 8f e8 ed f5 09 37 ad |...N..}.......7.| +00000040 06 c9 6b a4 d5 de 7f 07 07 a6 9d c7 c0 09 00 00 |..k.............| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -57,17 +58,17 @@ 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| 00000270 95 12 07 8f 2a 16 03 01 00 b5 0c 00 00 b1 03 00 |....*...........| -00000280 1d 20 68 5a 6f c6 20 26 b5 5c 47 c6 5e fb 23 c4 |. hZo. &.\G.^.#.| -00000290 bc 9c 3f 3a 9b ed d6 8e a3 c8 66 7d 9b cb d0 30 |..?:......f}...0| -000002a0 f9 60 00 8b 30 81 88 02 42 01 b2 fb f8 5f d0 14 |.`..0...B...._..| -000002b0 9d 3c 55 0f 16 50 6f d5 0c 4c 3e 73 2e a9 23 5f |.s..#_| -000002c0 e8 9c 02 5d 4c 6d b0 c1 9e 0d ac 59 36 6c d5 c2 |...]Lm.....Y6l..| -000002d0 4c 94 94 94 6f a4 df 26 1a 54 f5 74 b8 49 75 49 |L...o..&.T.t.IuI| -000002e0 9c aa cd 91 24 f3 52 88 6a 1e 80 02 42 01 81 a2 |....$.R.j...B...| -000002f0 76 e2 e8 b0 2a 8e 4e ed 6d be 2f e3 ca 4c ff f2 |v...*.N.m./..L..| -00000300 d3 14 c0 b5 f8 c5 53 04 97 de 14 b2 8e af 77 86 |......S.......w.| -00000310 de bf 4a 59 cf 7b 8a 73 d3 95 c3 28 ca 25 63 8e |..JY.{.s...(.%c.| -00000320 9e 02 7f 8a 04 bb 69 1e 41 31 76 2b 5a 54 ed 16 |......i.A1v+ZT..| +00000280 1d 20 3e 61 33 da 82 02 f5 6d 70 2d e5 07 df 43 |. >a3....mp-...C| +00000290 d7 e6 1a b2 81 3e 58 03 dc 27 37 34 3b 2e 5a d5 |.....>X..'74;.Z.| +000002a0 d4 1a 00 8b 30 81 88 02 42 00 8b 0c f4 0f fe 8c |....0...B.......| +000002b0 01 70 3a c5 e5 29 53 1c ad 6c f4 35 53 e3 e6 ce |.p:..)S..l.5S...| +000002c0 19 21 03 de f5 e3 df 8e e5 6b 43 00 08 b7 24 2c |.!.......kC...$,| +000002d0 27 9e 2b bc 2f 96 07 a0 f9 a9 6b d4 b7 75 a8 5d |'.+./.....k..u.]| +000002e0 99 13 ab 5a dd 35 56 08 6d 9c a1 02 42 01 29 62 |...Z.5V.m...B.)b| +000002f0 b9 64 8b 6d 91 b7 f5 59 73 9d 2d bc 9d 9a 5b 43 |.d.m...Ys.-...[C| +00000300 d8 d5 76 be 2a 8f c5 f0 2e 5d a8 be 7b d0 36 fe |..v.*....]..{.6.| +00000310 62 97 7f 17 96 f6 c3 b4 06 2a e2 cb 77 80 ff 28 |b........*..w..(| +00000320 02 64 cb bb c7 a9 77 4b 96 7d 07 11 7e e8 28 16 |.d....wK.}..~.(.| 00000330 03 01 00 0a 0d 00 00 06 03 01 02 40 00 00 16 03 |...........@....| 00000340 01 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) @@ -106,30 +107,30 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| -00000240 00 8d 00 8b 30 81 88 02 42 01 57 eb e6 90 3c fe |....0...B.W...<.| -00000250 10 8d e9 7d 50 a5 d3 83 43 64 e7 d0 cb 65 ef b9 |...}P...Cd...e..| -00000260 56 59 b9 52 09 e8 52 d7 d7 4d a7 57 09 dd 1f 83 |VY.R..R..M.W....| -00000270 22 0e 4c 4e 8b 50 0d 68 72 26 9e 2a 8b 6d cb 88 |".LN.P.hr&.*.m..| -00000280 c8 f4 0d 7d 85 80 e2 ec 7f f1 be 02 42 01 68 5d |...}........B.h]| -00000290 f8 91 45 82 61 7f 57 e2 2e b2 54 7d f3 11 11 44 |..E.a.W...T}...D| -000002a0 2f ee 48 91 17 5c 04 3d b8 0e eb ed 66 33 b1 62 |/.H..\.=....f3.b| -000002b0 61 a1 03 e8 77 cf 44 4b 93 fc 4f 12 24 2f d1 67 |a...w.DK..O.$/.g| -000002c0 c8 4b 07 e3 cb a8 7d 5d 82 d4 a2 ec d7 0b f8 14 |.K....}]........| -000002d0 03 01 00 01 01 16 03 01 00 30 28 45 dc 18 db 52 |.........0(E...R| -000002e0 a7 b5 1e 68 7a 06 03 8a 23 87 07 ea 79 38 29 ec |...hz...#...y8).| -000002f0 1b b7 b9 cb 1b 04 ac ba 1d b2 d5 8e 71 e0 27 30 |............q.'0| -00000300 02 d1 c9 4d 35 69 38 71 c9 c7 |...M5i8q..| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 90 0f 00 |...._X.;t.......| +00000240 00 8c 00 8a 30 81 87 02 41 46 5f cc 88 bc 2b e5 |....0...AF_...+.| +00000250 20 33 a9 ff 52 bb 25 dc cf a1 08 45 b5 82 9a 1b | 3..R.%....E....| +00000260 53 04 18 b4 23 20 c4 d2 d8 92 9b 21 a7 ec 36 d6 |S...# .....!..6.| +00000270 63 35 68 4c 21 c4 0e 20 07 0c 8f 38 2f 9b b7 9e |c5hL!.. ...8/...| +00000280 e7 9d 6d ea da 1c a6 f1 c5 d3 02 42 01 ed 54 c8 |..m........B..T.| +00000290 9e b2 45 f1 1f 77 ee e3 a7 3a 40 9b fe 9b 1d 38 |..E..w...:@....8| +000002a0 ff 9b b4 c6 e7 94 07 b8 5f 93 bd 38 8d 31 dd 80 |........_..8.1..| +000002b0 2f 82 6e b5 85 8f 15 8b cd b2 04 81 e2 0b 2a fa |/.n...........*.| +000002c0 d9 4b 47 0b 86 26 8b 4e 83 a6 15 9e 93 15 14 03 |.KG..&.N........| +000002d0 01 00 01 01 16 03 01 00 30 f3 06 0e 6f 16 1b 0b |........0...o...| +000002e0 46 54 37 fd c6 80 0f ec 4b dd d7 d4 17 b2 d7 8d |FT7.....K.......| +000002f0 4e 6a 7f 2a af d2 ea 19 11 8f 23 57 b7 e7 2f b3 |Nj.*......#W../.| +00000300 97 f6 93 3f ac 0d 5c f8 f5 |...?..\..| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 3d a8 df 2e 80 |..........0=....| -00000010 26 22 66 32 fb 6e bc 9e f5 d6 6a 5e 0a 18 34 92 |&"f2.n....j^..4.| -00000020 f9 42 40 e4 9c b1 7a 28 d2 52 e9 b8 13 ce 89 01 |.B@...z(.R......| -00000030 23 44 ab 2e 75 3e c2 96 f5 59 61 |#D..u>...Ya| +00000000 14 03 01 00 01 01 16 03 01 00 30 03 aa a1 4c bf |..........0...L.| +00000010 ab 53 f3 96 e7 db b1 a4 d7 19 f7 2f c0 b7 32 ea |.S........./..2.| +00000020 bd f3 4a 7c 0d 4c df a4 5f a0 3d f3 1b 57 65 a1 |..J|.L.._.=..We.| +00000030 d1 31 ae 52 6e ed 15 d2 d9 23 68 |.1.Rn....#h| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 64 ac d2 1b 98 4d 4e ec 22 25 35 |.... d....MN."%5| -00000010 7c 7c 79 15 a8 54 0d 93 1a b3 3e ff 68 27 d0 d5 |||y..T....>.h'..| -00000020 82 24 7b dc e7 17 03 01 00 20 98 da 6d 26 de b8 |.${...... ..m&..| -00000030 4b d0 ee 2c 18 52 05 86 59 b0 b6 e7 42 74 54 ea |K..,.R..Y...BtT.| -00000040 e6 96 de ec 82 dc 1f 3a 6c 5c 15 03 01 00 20 cc |.......:l\.... .| -00000050 11 da e4 75 e5 0c 06 84 e5 89 3e a4 ef 3c 28 10 |...u......>..<(.| -00000060 68 0a 6f d4 6e ae 14 a6 ca 7c ba 98 c4 28 7e |h.o.n....|...(~| +00000000 17 03 01 00 20 aa 0c f4 30 17 b7 59 47 33 91 07 |.... ...0..YG3..| +00000010 cc 52 7b 52 f8 a0 82 44 25 03 0e b4 45 6e 0c 5a |.R{R...D%...En.Z| +00000020 37 6d d6 6d 80 17 03 01 00 20 bc c7 70 3b 94 cc |7m.m..... ..p;..| +00000030 09 db 15 84 d8 b9 c5 cf d6 01 91 93 5b 20 5a b1 |............[ Z.| +00000040 6a 43 23 30 7e 02 ea 8b e0 28 15 03 01 00 20 c2 |jC#0~....(.... .| +00000050 7f c9 90 b3 ef c6 52 68 44 df 05 30 17 39 d9 42 |......RhD..0.9.B| +00000060 76 7a 1d a1 17 2b fa b4 92 ca 40 a9 58 d4 87 |vz...+....@.X..| diff --git a/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA index 687eba43e6c..de3de89cd16 100644 --- a/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA +++ b/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 48 c6 a1 aa 01 |....]...Y..H....| -00000010 b8 4b a1 f5 6d 71 28 f7 fd 76 9d 12 50 d3 56 e2 |.K..mq(..v..P.V.| -00000020 ca 77 d4 82 07 65 e2 c5 12 40 35 20 e3 ee 0a df |.w...e...@5 ....| -00000030 1f 4a d9 b3 a6 6f a0 24 49 8d ab d9 d8 3c 24 36 |.J...o.$I....<$6| -00000040 35 ba 64 8b 7d ec 29 91 d9 26 5e 61 c0 13 00 00 |5.d.}.)..&^a....| +00000000 16 03 01 00 5d 02 00 00 59 03 01 fc 68 73 9f 1a |....]...Y...hs..| +00000010 9d 3b 9b f9 10 cf b5 84 b9 31 f4 a8 e9 47 ab 33 |.;.......1...G.3| +00000020 55 42 0b c0 f2 8e fa e7 a0 39 55 20 56 cd 87 f6 |UB.......9U V...| +00000030 05 e0 b1 e9 aa b8 b2 ca 33 9d 46 02 fd d8 f0 11 |........3.F.....| +00000040 0e fc 96 7e b4 fa fc c2 f3 da c4 2b c0 13 00 00 |...~.......+....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,17 +62,17 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 55 51 65 |............ UQe| -000002d0 bb 06 22 d7 d6 97 39 d1 f4 dc 95 06 b3 a4 a7 00 |.."...9.........| -000002e0 d1 e5 98 bc 97 12 03 25 03 12 ab 20 4f 00 80 71 |.......%... O..q| -000002f0 8d 3c 54 44 ba df 73 92 76 16 d1 ec b1 de a2 27 |.>> Flow 3 (client to server) @@ -110,30 +111,30 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 90 0f 00 |...._X.;t.......| -00000240 00 8c 00 8a 30 81 87 02 41 79 c5 57 74 46 9a 18 |....0...Ay.WtF..| -00000250 ad e0 b0 ba 68 f5 0e e2 58 94 dc 73 84 5a f8 86 |....h...X..s.Z..| -00000260 86 8e 2a 37 82 02 a1 4b 19 cd 71 b3 99 04 64 b0 |..*7...K..q...d.| -00000270 db 4a cc 41 a6 17 28 38 f1 67 bd 59 16 97 71 32 |.J.A..(8.g.Y..q2| -00000280 06 71 24 2c f3 df 34 1b a3 b8 02 42 01 2f 2f db |.q$,..4....B.//.| -00000290 45 07 94 53 89 81 59 0b 92 9d 1a 05 42 b3 1c 40 |E..S..Y.....B..@| -000002a0 38 50 a1 8e a6 35 15 76 ca 75 7e fc 8d 7b 36 f3 |8P...5.v.u~..{6.| -000002b0 e3 e7 bf f9 bd 94 35 a0 c5 2b 35 88 be 5d ee f1 |......5..+5..]..| -000002c0 00 f9 9c a8 01 a8 92 5d d6 17 b6 54 98 e4 14 03 |.......]...T....| -000002d0 01 00 01 01 16 03 01 00 30 1f d6 11 ac 58 b3 20 |........0....X. | -000002e0 31 6d 3b f5 83 98 50 75 ff 4f 79 61 2b fc 0f 6c |1m;...Pu.Oya+..l| -000002f0 a6 4d 9e 65 38 e3 ca 12 76 0a 56 1e dd 73 da e1 |.M.e8...v.V..s..| -00000300 66 5a 33 62 8f 7d c3 ed ad |fZ3b.}...| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 00 8b 30 81 88 02 42 00 88 3e 14 10 fa b5 |....0...B..>....| +00000250 65 d8 03 71 7e b7 44 a5 db 04 85 d2 f4 5d c5 de |e..q~.D......]..| +00000260 71 e4 f9 ad 5e 47 6c 83 eb 6a 2b fc 8d 60 6b 1b |q...^Gl..j+..`k.| +00000270 55 89 7b 03 60 fb 9c b2 b1 42 ef 02 63 29 59 03 |U.{.`....B..c)Y.| +00000280 02 a8 48 4d 9a 3d f3 e9 6b ac 76 02 42 01 90 36 |..HM.=..k.v.B..6| +00000290 5d d0 ec dd 76 75 0c 97 66 7f 10 ec 1d 39 5e bb |]...vu..f....9^.| +000002a0 2c 81 9e 15 fa 59 3f e8 77 3f 33 03 b6 2d 02 5a |,....Y?.w?3..-.Z| +000002b0 28 82 53 7a 18 69 29 5b d9 7d ce 4f 94 d9 69 29 |(.Sz.i)[.}.O..i)| +000002c0 b2 84 87 4a 15 47 c6 da 6f c3 df ca 8a 58 0b 14 |...J.G..o....X..| +000002d0 03 01 00 01 01 16 03 01 00 30 89 15 96 15 9d 93 |.........0......| +000002e0 e3 ae 94 14 f9 ea 39 d7 3b d6 98 e1 ed c8 0a 3f |......9.;......?| +000002f0 6f 2c a2 9b cd c5 ea 1a 1f 27 89 1a 7d ff 60 07 |o,.......'..}.`.| +00000300 22 1f bc b8 56 3a ee 24 5a ff |"...V:.$Z.| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 92 36 25 46 a5 |..........0.6%F.| -00000010 44 e6 31 25 cd 24 15 df 13 f8 5b a3 af 7c 12 43 |D.1%.$....[..|.C| -00000020 b8 8c 39 84 bc 25 06 02 02 86 78 20 1b ec 98 1a |..9..%....x ....| -00000030 31 b3 b8 cf 82 92 77 ff 08 87 fb |1.....w....| +00000000 14 03 01 00 01 01 16 03 01 00 30 bf 0c 82 bd 43 |..........0....C| +00000010 ba 60 ec df 88 4d 48 be d5 c4 0c b5 7d c4 94 c4 |.`...MH.....}...| +00000020 15 6e 50 45 77 56 ce d5 e0 4c 15 fc da 96 0b 41 |.nPEwV...L.....A| +00000030 fd 70 39 e9 33 3f 57 77 f5 a3 67 |.p9.3?Ww..g| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 2f bd ab e0 2f 9a 81 58 99 35 bb |.... /.../..X.5.| -00000010 86 61 6e 15 be 31 d7 ad 44 1d d9 cf 2f fc d9 f6 |.an..1..D.../...| -00000020 da b6 48 32 27 17 03 01 00 20 76 70 b7 7d 1b 05 |..H2'.... vp.}..| -00000030 ee 54 99 bf 89 79 79 b5 68 c1 84 3c 6d 47 5c d1 |.T...yy.h..>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 6f 48 26 41 da |....]...Y..oH&A.| -00000010 73 82 d1 cf 84 ad 06 e9 76 39 dc e4 c8 34 af 53 |s.......v9...4.S| -00000020 06 ed ed 68 56 5f 76 11 4e f6 ff 20 55 fd 29 c5 |...hV_v.N.. U.).| -00000030 aa 56 af bd 5d 67 74 4f 08 8a 52 a1 7e cd b9 ac |.V..]gtO..R.~...| -00000040 31 a0 2f 45 25 1f b2 24 71 26 80 17 c0 09 00 00 |1./E%..$q&......| +00000000 16 03 01 00 5d 02 00 00 59 03 01 ef c9 5c 4d 29 |....]...Y....\M)| +00000010 07 24 2a 41 08 94 39 cc d3 fb 92 88 1c ff 64 6b |.$*A..9.......dk| +00000020 0a 14 41 89 c6 5d 9b 25 7e a7 04 20 a0 aa ad 46 |..A..].%~.. ...F| +00000030 14 01 d2 dd 37 44 05 4b 1d 9f ea e5 98 29 1e 36 |....7D.K.....).6| +00000040 09 e2 ab 90 93 ee c1 99 7d 17 77 9b c0 09 00 00 |........}.w.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -56,20 +57,20 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 01 00 b3 0c 00 00 af 03 00 |....*...........| -00000280 1d 20 51 4c 6f eb 08 70 52 20 15 78 d3 f8 65 5e |. QLo..pR .x..e^| -00000290 0f 59 03 b7 d1 0e e9 7e be 42 d2 cd f3 57 c6 24 |.Y.....~.B...W.$| -000002a0 6b 2c 00 89 30 81 86 02 41 7b 1b ec 11 08 f4 8f |k,..0...A{......| -000002b0 db 2c c5 1b 33 b2 b0 b4 da 76 b9 a7 78 ed ee 0e |.,..3....v..x...| -000002c0 23 5c 4b b0 10 6e 41 12 b9 d4 68 c1 15 ea 70 0a |#\K..nA...h...p.| -000002d0 0c 91 c1 8d 4a 4d 41 c1 c3 25 f1 90 ef 95 f3 e1 |....JMA..%......| -000002e0 a8 30 4d ce 4d d1 eb 8c cf 9a 02 41 09 e0 8c 8e |.0M.M......A....| -000002f0 70 01 f1 5d b2 8a d1 61 bc 86 f4 85 2f 6c ac 2c |p..]...a..../l.,| -00000300 e8 bf 20 c7 81 46 21 6e 9b bd c1 83 71 34 8d 65 |.. ..F!n....q4.e| -00000310 fc 35 07 be c8 ad d4 3a c6 7b 40 1c f7 17 e3 d9 |.5.....:.{@.....| -00000320 96 19 d4 cd 0d d0 8c 4f b2 09 6a 4b 05 16 03 01 |.......O..jK....| -00000330 00 0a 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 |.........@......| -00000340 04 0e 00 00 00 |.....| +00000270 95 12 07 8f 2a 16 03 01 00 b4 0c 00 00 b0 03 00 |....*...........| +00000280 1d 20 a4 4e 43 df 00 5c c7 1c e8 d4 8e 9b cf b0 |. .NC..\........| +00000290 36 85 64 7c d7 69 95 c0 b4 6f d8 0b 45 b8 a4 34 |6.d|.i...o..E..4| +000002a0 1a 18 00 8a 30 81 87 02 42 01 d0 4a 3f 65 9d 46 |....0...B..J?e.F| +000002b0 20 80 34 28 12 93 56 6e dc e4 0e 91 0b 45 4b 83 | .4(..Vn.....EK.| +000002c0 c5 e9 83 2c 41 d6 dc 49 15 15 e6 65 9f 18 ba a6 |...,A..I...e....| +000002d0 20 a6 de c7 20 7e 09 71 e6 59 86 9e aa 32 be 43 | ... ~.q.Y...2.C| +000002e0 b7 c3 27 98 ba 5b 49 9b 1d b9 67 02 41 4e 36 0e |..'..[I...g.AN6.| +000002f0 6d 29 c8 7d 0b d9 6f 06 92 ca 0b b9 33 7e 11 58 |m).}..o.....3~.X| +00000300 2f cc 06 ae ad 57 80 f4 38 a1 8a e3 6a ef 37 86 |/....W..8...j.7.| +00000310 58 1a 59 f9 4a 9a 64 89 5b 7c 8a 7a c5 78 dd b5 |X.Y.J.d.[|.z.x..| +00000320 6c 96 b8 23 ff fc 88 20 59 0b e9 74 99 b9 16 03 |l..#... Y..t....| +00000330 01 00 0a 0d 00 00 06 03 01 02 40 00 00 16 03 01 |..........@.....| +00000340 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| 00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| @@ -106,29 +107,29 @@ 00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| -00000230 86 0f 00 00 82 00 80 59 18 58 aa 18 70 84 a3 26 |.......Y.X..p..&| -00000240 8c 1d 77 52 a7 2d 00 e5 00 dc 24 1c f6 9b 9f 63 |..wR.-....$....c| -00000250 c8 84 8b dc e7 61 78 9c 28 0d 4c 3a 1e 5f a7 ce |.....ax.(.L:._..| -00000260 35 17 1c b1 de e0 01 32 35 6f 85 59 22 73 50 2a |5......25o.Y"sP*| -00000270 36 df 39 0c c8 c1 45 70 a2 e4 53 bb de e6 0e 6a |6.9...Ep..S....j| -00000280 fd 45 8e 4d eb 1f de 86 d3 fb 94 e4 8d 22 cd 30 |.E.M.........".0| -00000290 e7 29 de 65 f0 2a cd b8 3d b5 be 91 a3 7d 3b 30 |.).e.*..=....};0| -000002a0 1a a5 63 bd 84 1f 95 19 d1 fe 25 40 b8 8f ab 96 |..c.......%@....| -000002b0 59 42 e6 31 93 c0 39 14 03 01 00 01 01 16 03 01 |YB.1..9.........| -000002c0 00 30 a9 f7 c0 97 f4 b8 06 65 a6 7c fb 80 a1 79 |.0.......e.|...y| -000002d0 5f 44 72 55 13 d1 ca e3 9a 91 5d 1e 08 93 6d b5 |_DrU......]...m.| -000002e0 1c 5e 52 24 b1 ec db aa 3b bc fe db 18 0b 18 fe |.^R$....;.......| -000002f0 51 6a |Qj| +00000230 86 0f 00 00 82 00 80 a4 68 2d 1f 8a 97 43 76 aa |........h-...Cv.| +00000240 f9 24 95 20 62 13 c0 a3 45 c6 18 1c a3 34 70 02 |.$. b...E....4p.| +00000250 ff f5 01 4e ba e2 20 1c f9 06 a6 67 92 d9 e6 9d |...N.. ....g....| +00000260 a3 49 e0 75 3e 11 00 74 52 b1 36 58 4b 1e 54 83 |.I.u>..tR.6XK.T.| +00000270 e0 9a 48 4d df 2c ab fd cd 5e 7a cf c9 b8 32 08 |..HM.,...^z...2.| +00000280 74 e6 ae 75 20 f4 41 3a 7c a9 a3 19 38 a0 8d 05 |t..u .A:|...8...| +00000290 0a e9 3e 50 6c f6 f8 a3 89 a9 55 ea dc 3f be b1 |..>Pl.....U..?..| +000002a0 0a 92 83 cc f0 9b c9 e1 49 13 db 64 be 55 46 b5 |........I..d.UF.| +000002b0 12 b1 0b 88 32 e3 f1 14 03 01 00 01 01 16 03 01 |....2...........| +000002c0 00 30 81 77 0f 6c 7a bc a8 d2 41 f9 8b a7 da 96 |.0.w.lz...A.....| +000002d0 29 f1 2f b1 31 f3 57 03 09 21 5c fa dc f7 5c f6 |)./.1.W..!\...\.| +000002e0 7f a8 24 08 30 70 bb 34 16 22 f8 c6 b2 4d a7 16 |..$.0p.4."...M..| +000002f0 68 61 |ha| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 e6 36 50 e7 a3 |..........0.6P..| -00000010 72 0a 6a 9f 18 17 91 51 ad 48 19 54 c8 6b c0 45 |r.j....Q.H.T.k.E| -00000020 d5 9b cb 08 34 d3 3a 73 74 04 3a 3d 24 b0 95 48 |....4.:st.:=$..H| -00000030 97 9e c5 83 4f 20 29 c8 dd 93 6c |....O )...l| +00000000 14 03 01 00 01 01 16 03 01 00 30 71 d2 ee cd f8 |..........0q....| +00000010 c5 fe b4 96 d5 02 ee cb f7 f8 93 34 f2 8a ed 71 |...........4...q| +00000020 9a b7 1f 01 9d fb 6c 3f ee 22 bb 5c b0 8c 08 f5 |......l?.".\....| +00000030 bf 1e d3 1c 12 ec 7b 86 05 bd e5 |......{....| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 58 a1 0a 68 2c 04 68 7d e9 13 ce |.... X..h,.h}...| -00000010 69 4b 53 4a f6 fc e0 c8 0e 05 ad 19 d8 b3 37 67 |iKSJ..........7g| -00000020 f2 1f 3b 33 62 17 03 01 00 20 c2 e7 d3 d2 38 ba |..;3b.... ....8.| -00000030 27 13 ed d1 73 fc 9b f5 4f 61 f0 35 27 8e 54 52 |'...s...Oa.5'.TR| -00000040 b7 ce bd 6a 05 c6 61 95 1e 8a 15 03 01 00 20 6e |...j..a....... n| -00000050 07 21 86 31 f8 74 6b 45 4d 10 2f 5d e7 2b 64 77 |.!.1.tkEM./].+dw| -00000060 a9 7f 1e 49 ed d5 d4 1e 2e f2 b1 c5 4d 02 46 |...I........M.F| +00000000 17 03 01 00 20 8a 57 b3 89 76 41 f0 b3 51 da f4 |.... .W..vA..Q..| +00000010 e7 6a f8 46 75 77 4d 8b 67 41 f9 f9 eb a0 cd 12 |.j.FuwM.gA......| +00000020 78 08 12 d1 7b 17 03 01 00 20 9d 44 6a dd 48 ad |x...{.... .Dj.H.| +00000030 0a d9 3f 80 da b1 3d b3 50 be 40 c1 85 b5 bb 59 |..?...=.P.@....Y| +00000040 e8 b9 2a 9f f5 2e 98 d3 2b c1 15 03 01 00 20 bd |..*.....+..... .| +00000050 69 41 45 bb 53 de f8 b7 bf a5 87 12 02 32 1a 05 |iAE.S........2..| +00000060 09 94 40 a5 64 b3 31 7d 0d dc 01 ff 25 ca 31 |..@.d.1}....%.1| diff --git a/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA index 48eb1ce6419..37d05fc4819 100644 --- a/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA +++ b/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 24 71 03 c6 1d |....]...Y..$q...| -00000010 d4 f5 09 b2 3c d8 88 51 57 4c 90 07 4b 74 fe 1d |....<..QWL..Kt..| -00000020 c9 7f 00 78 9b a3 b2 1b ef 43 66 20 07 97 7c a6 |...x.....Cf ..|.| -00000030 9b c6 a9 47 42 ae 99 bf 59 fe 52 f6 da d9 1c 68 |...GB...Y.R....h| -00000040 c2 7a 53 3f 27 0d 11 87 9a 47 81 5c c0 13 00 00 |.zS?'....G.\....| +00000000 16 03 01 00 5d 02 00 00 59 03 01 71 32 68 84 f2 |....]...Y..q2h..| +00000010 93 91 32 5b 71 e6 d1 fd 26 83 00 87 0f 56 f3 8a |..2[q...&....V..| +00000020 70 17 5e c9 c3 b3 ce 61 9a 1d 4d 20 85 cc 39 26 |p.^....a..M ..9&| +00000030 32 1a 78 34 d5 d3 6c e2 df 89 f5 a0 51 2c f5 2d |2.x4..l.....Q,.-| +00000040 e0 17 51 e7 51 f4 61 8d 35 72 75 92 c0 13 00 00 |..Q.Q.a.5ru.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,17 +62,17 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 ad a7 d5 |............ ...| -000002d0 fc 63 e1 22 f8 1f 8d ad 50 09 1a 92 a4 57 ea 88 |.c."....P....W..| -000002e0 6d 9c 20 70 f1 8b 85 15 ec 8e b2 b3 07 00 80 b1 |m. p............| -000002f0 03 03 a7 cf 8f 73 e2 a3 29 0d 55 4a 06 72 db e5 |.....s..).UJ.r..| -00000300 65 41 44 49 05 1c 37 17 1c 02 6e b1 f4 e8 a9 bb |eADI..7...n.....| -00000310 00 24 3e 3a 3c d6 1c f6 dd 21 a4 e3 61 b0 1d 2e |.$>:<....!..a...| -00000320 77 11 53 51 4d 49 1e 07 bf 07 61 d1 54 f4 c7 24 |w.SQMI....a.T..$| -00000330 4f 7d 5c 5a fb 84 c0 9d 0e 52 12 b6 40 72 37 fd |O}\Z.....R..@r7.| -00000340 8c bd d0 8a b1 9e 2c 18 bc 04 a3 c2 90 a3 33 4c |......,.......3L| -00000350 06 7c 14 a8 73 7d d2 23 30 f9 31 12 56 31 60 19 |.|..s}.#0.1.V1`.| -00000360 d1 0d 31 c1 3c 25 66 62 5c 9b 13 5e 34 c6 69 16 |..1.<%fb\..^4.i.| +000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 3a 64 e7 |............ :d.| +000002d0 9a 59 c3 4e fc 40 5e 2f 5c 89 cd e1 94 85 4e 1f |.Y.N.@^/\.....N.| +000002e0 29 37 0b 53 fe 3a 13 76 56 25 2a 97 65 00 80 08 |)7.S.:.vV%*.e...| +000002f0 1c de 63 0d 31 9b 72 7b 85 0c 03 b0 08 ea 80 a1 |..c.1.r{........| +00000300 ee 00 03 f9 29 a3 ba 8e c8 71 3e b4 4d b3 28 54 |....)....q>.M.(T| +00000310 2c e7 11 3a 15 e0 43 06 f0 36 15 50 54 5e 88 48 |,..:..C..6.PT^.H| +00000320 ac c4 68 db 83 dc 0c 22 e4 99 4a 08 2a 00 7d 19 |..h...."..J.*.}.| +00000330 0d 74 ba 7a 27 9c 39 dc 29 41 52 cf a2 ac 29 94 |.t.z'.9.)AR...).| +00000340 e6 b0 87 60 e5 d3 58 af 3e 8e 41 bd be 48 ba 90 |...`..X.>.A..H..| +00000350 49 b2 b1 d3 8e b0 49 98 4a 12 70 60 c7 57 d9 a7 |I.....I.J.p`.W..| +00000360 db dc 41 b0 dc 81 37 1b 6d ac 9c 69 12 f4 fa 16 |..A...7.m..i....| 00000370 03 01 00 0a 0d 00 00 06 03 01 02 40 00 00 16 03 |...........@....| 00000380 01 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) @@ -110,29 +111,29 @@ 00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| -00000230 86 0f 00 00 82 00 80 59 e2 7d 00 66 f0 59 a0 19 |.......Y.}.f.Y..| -00000240 b6 4f 26 80 ad 31 b4 b3 c2 56 af 84 bf 88 15 7f |.O&..1...V......| -00000250 dc 29 fc 51 f2 cf 0d ec 52 46 c5 c5 cd 24 c1 93 |.).Q....RF...$..| -00000260 5b f6 06 09 ad bb 9a 4a ae 5d ec 57 f8 96 a8 b1 |[......J.].W....| -00000270 4b 81 45 7d 34 38 59 ea 76 47 76 1c 7f 7b 68 e9 |K.E}48Y.vGv..{h.| -00000280 89 7b 5d 4c b9 bc 5a 26 e1 f7 6c 42 f7 c6 6d bb |.{]L..Z&..lB..m.| -00000290 c0 c7 bd f6 5e 9e 51 d8 30 ec 9f da 56 0a b7 2a |....^.Q.0...V..*| -000002a0 6c 5e 50 d1 74 48 70 4a 88 62 16 a1 ba f2 01 e5 |l^P.tHpJ.b......| -000002b0 00 b6 eb cb e3 18 cf 14 03 01 00 01 01 16 03 01 |................| -000002c0 00 30 61 51 84 02 46 3c 10 62 b5 2a a2 8b 4e 2d |.0aQ..F<.b.*..N-| -000002d0 57 55 26 c5 46 f2 5d a1 f5 20 46 0d 63 fd 48 5a |WU&.F.].. F.c.HZ| -000002e0 f3 65 90 8c 1a bd 59 6e 5f d1 5c b6 ee 33 49 12 |.e....Yn_.\..3I.| -000002f0 46 ec |F.| +00000230 86 0f 00 00 82 00 80 21 34 0c d8 10 ac 90 53 f9 |.......!4.....S.| +00000240 18 52 42 05 ca e8 c7 4f 33 c4 43 4b 8e 7c e4 23 |.RB....O3.CK.|.#| +00000250 21 6d e4 07 ef 3f 06 d1 ea 1c 9d 3b e0 d2 66 36 |!m...?.....;..f6| +00000260 b5 c9 a1 da fe 54 fd e0 fe 0c b6 12 90 93 41 1f |.....T........A.| +00000270 43 00 00 e4 a4 04 14 af 00 3e 1b db 16 d6 07 4b |C........>.....K| +00000280 55 2f ed 55 e1 e1 a8 8b d8 e1 fe cb 41 1d fe bc |U/.U........A...| +00000290 6d d9 ba 8f 2b 1c 26 19 9d 93 a9 78 fb 8a 54 59 |m...+.&....x..TY| +000002a0 76 3b 0a df e6 71 2c c0 63 dd 22 8d c6 70 ef 0e |v;...q,.c."..p..| +000002b0 4f 1b 4c da 65 11 f6 14 03 01 00 01 01 16 03 01 |O.L.e...........| +000002c0 00 30 b5 c2 b0 f3 b6 6c 4a 99 de f2 98 2f 37 2b |.0.....lJ..../7+| +000002d0 8a d8 ab 96 91 c2 9b cc 56 5c fb e1 4f 5b 89 09 |........V\..O[..| +000002e0 5f 94 05 60 0e 83 b5 49 9a 15 9b 0f 5d 1a 2b a2 |_..`...I....].+.| +000002f0 11 23 |.#| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 b1 3c 7f c3 15 |..........0.<...| -00000010 e4 fe bc 1a ee 0d ec 28 ce b0 f7 fd a4 0a e4 79 |.......(.......y| -00000020 37 09 68 de 58 f8 e8 76 7d 9c 09 35 42 7e 00 8e |7.h.X..v}..5B~..| -00000030 4c 8d d1 60 26 d4 09 c5 8b d0 96 |L..`&......| +00000000 14 03 01 00 01 01 16 03 01 00 30 63 a2 f0 9b 1c |..........0c....| +00000010 48 6d 23 54 62 b1 2a 19 e7 89 51 fd 0d 83 97 87 |Hm#Tb.*...Q.....| +00000020 9b 73 31 11 5e 42 56 62 62 37 4d e5 e6 72 8a 6d |.s1.^BVbb7M..r.m| +00000030 a3 02 2b 2c 9e a5 1a 5c 34 f2 0d |..+,...\4..| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 6c bb 09 ee 1d 96 6c 63 5b b6 69 |.... l.....lc[.i| -00000010 bf ea ad 7a 85 36 a2 4b d2 f0 73 18 91 b1 42 e5 |...z.6.K..s...B.| -00000020 77 d0 6c ff ab 17 03 01 00 20 ed 85 78 3b bd 49 |w.l...... ..x;.I| -00000030 2c f3 02 24 f2 18 72 96 a0 49 6b 06 bd bb 54 25 |,..$..r..Ik...T%| -00000040 0a 3e ff 07 45 6b 6c cc a6 d2 15 03 01 00 20 07 |.>..Ekl....... .| -00000050 9a fb b7 cc 01 cd f7 b6 90 d3 b6 a7 31 15 99 e2 |............1...| -00000060 e7 e8 2b a5 c0 e8 a9 9d fe 4e 11 0d 4a d4 b7 |..+......N..J..| +00000000 17 03 01 00 20 63 1a 2c 25 27 68 ed de ba 94 52 |.... c.,%'h....R| +00000010 73 f2 7a 28 ed 8c e9 3f a2 48 9a 07 62 22 27 6d |s.z(...?.H..b"'m| +00000020 4e be ba e4 67 17 03 01 00 20 1d ee ac 7c fc a7 |N...g.... ...|..| +00000030 df 74 93 16 c6 ec 58 5e 04 5d 2e 98 0a ba 52 4f |.t....X^.]....RO| +00000040 a0 02 c5 79 c3 d6 f0 ab 8d 33 15 03 01 00 20 bb |...y.....3.... .| +00000050 54 a6 65 a7 c9 03 e7 83 ae a1 f3 26 9f 73 76 6b |T.e........&.svk| +00000060 e6 1e f7 e0 76 e5 ca 9f c8 87 14 ac 27 f1 e3 |....v.......'..| diff --git a/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES index ac354c50bc6..a8593e249b0 100644 --- a/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 70 d2 b8 0b 74 |....]...Y..p...t| -00000010 93 b4 60 d7 ab 1d 0f f3 7c d0 b5 f8 a2 78 45 30 |..`.....|....xE0| -00000020 b1 41 9b b6 73 bd 05 d8 85 16 66 20 e8 26 8d 7a |.A..s.....f .&.z| -00000030 e2 da e0 a0 7a c9 19 d1 dd db 2b bc b4 b2 56 39 |....z.....+...V9| -00000040 9f e6 62 75 29 96 40 b3 0d c0 db 65 c0 09 00 00 |..bu).@....e....| +00000000 16 03 01 00 5d 02 00 00 59 03 01 3e 61 ab b7 94 |....]...Y..>a...| +00000010 d9 7c 76 db 26 b6 fc 86 00 8f c4 af bd c6 1a 22 |.|v.&.........."| +00000020 dd 72 ce 5d 2a 4c d8 61 a1 20 6b 20 c9 82 ca c9 |.r.]*L.a. k ....| +00000030 99 59 80 37 6c 01 d2 b3 b5 0d 68 9f 65 b0 15 7d |.Y.7l.....h.e..}| +00000040 a6 b0 15 b0 49 5a ae 38 d2 77 5e 06 c0 09 00 00 |....IZ.8.w^.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -56,37 +57,37 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 01 00 b4 0c 00 00 b0 03 00 |....*...........| -00000280 1d 20 5f 81 8f 18 31 4e 64 fe 87 f2 da c6 45 45 |. _...1Nd.....EE| -00000290 54 e3 54 c6 a0 bb bf bd d1 01 c5 7b 08 d8 32 6b |T.T........{..2k| -000002a0 a8 31 00 8a 30 81 87 02 42 01 21 7e c2 26 cb 5e |.1..0...B.!~.&.^| -000002b0 f1 2a d2 9b 7f 3f b4 d4 28 5e 63 5a 20 aa 28 87 |.*...?..(^cZ .(.| -000002c0 bb dd 5c 6a 91 a2 2d 03 7a 69 67 8b ca 84 a6 1f |..\j..-.zig.....| -000002d0 d3 58 40 eb 5c 54 95 96 05 d0 37 63 e4 a6 1b 51 |.X@.\T....7c...Q| -000002e0 9a d0 93 31 82 e6 8e a0 af 29 64 02 41 4c ff ac |...1.....)d.AL..| -000002f0 44 74 e0 04 2c ab 1c 23 91 dc 06 36 ff 19 a1 60 |Dt..,..#...6...`| -00000300 19 d4 e5 d3 78 f5 ed d8 09 7b de 61 6f 65 2c 69 |....x....{.aoe,i| -00000310 a1 d2 5d 07 bf 99 26 2b 70 fa 34 26 30 41 59 3b |..]...&+p.4&0AY;| -00000320 bc a3 10 9c 92 fa 60 a7 df ea e4 8a 3a 76 16 03 |......`.....:v..| -00000330 01 00 04 0e 00 00 00 |.......| +00000270 95 12 07 8f 2a 16 03 01 00 b5 0c 00 00 b1 03 00 |....*...........| +00000280 1d 20 73 36 95 70 b0 c6 fd c6 cf 68 f3 77 1e 46 |. s6.p.....h.w.F| +00000290 c2 22 3e f8 e6 f4 37 82 73 8e 8d ec 40 64 0d a9 |.">...7.s...@d..| +000002a0 f7 6f 00 8b 30 81 88 02 42 01 2f 8b 24 b7 24 65 |.o..0...B./.$.$e| +000002b0 6e f8 a3 55 53 3f da 67 a2 b6 35 b3 ef 8b 87 39 |n..US?.g..5....9| +000002c0 2f 44 e8 a6 9d 2c 16 c1 82 a9 a9 f6 20 0f 1b 36 |/D...,...... ..6| +000002d0 32 b8 7a 96 2d 5a b0 4d 43 53 ec c9 06 82 83 0e |2.z.-Z.MCS......| +000002e0 fb 0b 8c f8 0b 47 b6 dd 19 4c 96 02 42 01 c6 7e |.....G...L..B..~| +000002f0 20 9e d9 2f 33 1f 5f 25 bc 79 a3 df 96 9d e0 05 | ../3._%.y......| +00000300 d7 72 75 29 7d b3 f2 0a 5e 81 39 71 b7 f9 68 e8 |.ru)}...^.9q..h.| +00000310 82 07 93 80 88 31 77 2c db 8b 58 49 28 c5 7b c1 |.....1w,..XI(.{.| +00000320 e3 84 3c b9 08 2e a0 ab 66 12 b9 3c b9 a2 e8 16 |..<.....f..<....| +00000330 03 01 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 6d 2a 91 d7 c3 8f 1c d8 d4 cc 67 |....0m*........g| -00000040 ed 07 41 c2 9c 48 0d bd 7f 11 61 00 58 23 55 88 |..A..H....a.X#U.| -00000050 f9 bd da 92 bc e4 8d 47 c0 ac 72 43 7f 2d 0f b5 |.......G..rC.-..| -00000060 de bb 67 6e 9f |..gn.| +00000030 16 03 01 00 30 9a 24 ee 81 ee 6e b3 fe ab 63 04 |....0.$...n...c.| +00000040 ae b1 1b 11 91 b0 cc 45 b8 67 74 9e 92 15 fd b1 |.......E.gt.....| +00000050 b4 49 49 b4 f4 a5 61 01 1b ec 91 23 ec c0 98 8d |.II...a....#....| +00000060 ee 21 fd 29 95 |.!.).| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 be 25 a7 fa 04 |..........0.%...| -00000010 a5 dd 58 c1 5f a6 31 f8 fc fc db 27 a1 c7 0b 7c |..X._.1....'...|| -00000020 a5 9a 0f bd 07 09 d9 9b 95 bf f4 a5 80 c7 7d bd |..............}.| -00000030 a0 37 25 68 46 63 37 37 5f 3d b2 |.7%hFc77_=.| +00000000 14 03 01 00 01 01 16 03 01 00 30 74 d2 f1 68 1e |..........0t..h.| +00000010 1e 11 8a eb 51 ae a6 19 af 60 09 c4 85 65 3e 71 |....Q....`...e>q| +00000020 af d0 94 14 c3 80 18 91 72 23 97 26 f8 91 2f d6 |........r#.&../.| +00000030 65 3c 02 06 10 d0 bb e7 92 57 b0 |e<.......W.| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 98 6e bd 0c 0e 46 88 05 6d 67 b3 |.... .n...F..mg.| -00000010 a7 92 7a 3c f2 98 8b ab 07 9e 80 bc 7a 5e 70 1a |..z<........z^p.| -00000020 2b 3d 2f 28 c9 17 03 01 00 20 f1 a8 ac 45 f6 60 |+=/(..... ...E.`| -00000030 ac 76 4e 66 1b a1 23 65 9c 55 6b 0b d4 cb 0a 43 |.vNf..#e.Uk....C| -00000040 42 d1 1e 1b 61 45 16 8e a8 c2 15 03 01 00 20 3d |B...aE........ =| -00000050 c0 ac 27 49 be 69 0e 23 cd 1b ea 01 0f 97 66 34 |..'I.i.#......f4| -00000060 f8 bd a6 40 35 af 5b 1f cf 42 25 54 aa 2f 2e |...@5.[..B%T./.| +00000000 17 03 01 00 20 bf f3 92 9c 91 50 02 1e d2 29 17 |.... .....P...).| +00000010 2c 5d 5f 43 c9 de 49 db 7b 0b bf eb 77 c5 9a 37 |,]_C..I.{...w..7| +00000020 c7 e1 c3 83 a3 17 03 01 00 20 df 80 0b 7e 80 39 |......... ...~.9| +00000030 b3 46 d8 7c 09 7a a8 c1 3a 04 77 2f 94 30 eb 8e |.F.|.z..:.w/.0..| +00000040 5d 56 08 95 bb 50 80 76 4b e7 15 03 01 00 20 0e |]V...P.vK..... .| +00000050 91 ba 25 bb d6 f6 ee 42 e0 8e 08 a1 7f d5 8f e3 |..%....B........| +00000060 18 05 85 24 b6 0c 81 80 98 89 ae 2c 04 0e 8a |...$.......,...| diff --git a/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES index 694cd4ce892..b73fd761c46 100644 --- a/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES +++ b/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 5a a9 a1 6f fa |....]...Y..Z..o.| -00000010 19 95 38 9e 68 42 d7 0f 73 23 09 3f 01 5f e8 ae |..8.hB..s#.?._..| -00000020 d7 06 a2 9b d3 01 0f 0d 23 53 7d 20 55 2b 67 4e |........#S} U+gN| -00000030 8b 44 94 a5 25 ef b7 fb e1 c7 85 e8 15 60 f9 d7 |.D..%........`..| -00000040 6d a4 3f 3d 42 d7 78 a6 41 49 b7 12 c0 13 00 00 |m.?=B.x.AI......| +00000000 16 03 01 00 5d 02 00 00 59 03 01 79 f2 d6 96 d6 |....]...Y..y....| +00000010 6d c9 a1 7a 04 ba 6d 7d 29 8d 91 3f 8e 2e 17 0f |m..z..m})..?....| +00000020 c8 c4 3a e1 3c 64 00 28 f8 21 9d 20 16 7b 80 30 |..:...| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 a7 ec f4 |............ ...| -000002d0 c7 51 5e a0 fb 55 5a 01 34 cc d1 a6 22 df d6 00 |.Q^..UZ.4..."...| -000002e0 f5 73 e0 9e b8 9d 2a a9 49 3a 99 ba 17 00 80 14 |.s....*.I:......| -000002f0 95 47 77 a1 48 b4 e7 ba 6a e8 0e 4e ee 55 25 f5 |.Gw.H...j..N.U%.| -00000300 ea 82 65 b4 3f db a2 94 03 cc d3 6c 4a e6 cf 57 |..e.?......lJ..W| -00000310 25 4c 79 b8 fb ab dd 1f 68 e4 55 87 b1 46 12 30 |%Ly.....h.U..F.0| -00000320 5e 9f 3d 4a 52 24 76 50 c8 54 83 a2 b9 f5 a6 e0 |^.=JR$vP.T......| -00000330 ec e1 fb ae dd ca d2 c9 b2 31 d5 d4 73 f4 c0 0a |.........1..s...| -00000340 29 1c d3 8e 87 4c b4 0a 37 e8 77 e4 e2 a7 e9 9c |)....L..7.w.....| -00000350 04 ba af 31 dc 2e 5a b3 2e f3 58 e6 21 0a e2 1c |...1..Z...X.!...| -00000360 d4 c6 be b1 70 83 22 05 f8 78 12 6e bd 53 22 16 |....p."..x.n.S".| +000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 69 9e db |............ i..| +000002d0 5f 4b 5e 7d 1e 00 1e 91 a6 49 81 e3 d9 ee ea 5e |_K^}.....I.....^| +000002e0 5c 40 f0 68 fd dd eb 6e e4 85 58 91 70 00 80 8e |\@.h...n..X.p...| +000002f0 d6 64 01 3a 56 c2 58 5c 60 28 bc f6 bd 1e bf 73 |.d.:V.X\`(.....s| +00000300 21 b8 1a ea fb c2 df d5 f1 b9 4d d7 6f 1c 8b 24 |!.........M.o..$| +00000310 99 35 a5 ef 20 75 00 3e 83 34 da 40 4e ec e3 43 |.5.. u.>.4.@N..C| +00000320 04 a4 f2 1e bb 97 23 3e 21 32 88 43 80 99 ec 43 |......#>!2.C...C| +00000330 66 c3 09 87 1e e2 ad bb c3 1c db f7 9a 59 3a a8 |f............Y:.| +00000340 46 43 b6 3d 9a 6e c3 42 5b 1a 7d 85 dc db 96 cc |FC.=.n.B[.}.....| +00000350 8d 06 cc 08 d2 f0 09 c3 c6 ed 5f 3b f6 b0 a3 69 |.........._;...i| +00000360 6c a8 9a a5 ef ad 59 c1 07 96 e8 34 1d f0 d9 16 |l.....Y....4....| 00000370 03 01 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 0f 56 a4 2c c6 11 a2 0a a8 f7 ff |....0.V.,.......| -00000040 6e 71 19 e9 e5 c0 e2 6b 86 9b b1 5d 46 8d 62 93 |nq.....k...]F.b.| -00000050 69 7c 28 6f 25 3d dc ce fa 6f 91 9e b8 8c 15 cd |i|(o%=...o......| -00000060 6a b1 72 ce a8 |j.r..| +00000030 16 03 01 00 30 d1 17 2f 22 e5 fa 78 a0 b3 d3 22 |....0../"..x..."| +00000040 ab cb d2 54 52 e6 b2 74 11 bd 3c 69 9a 71 e8 69 |...TR..t..>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 d0 aa 00 27 9e |..........0...'.| -00000010 fb 56 22 9f 65 ab 3c cf 34 d9 a0 92 08 62 f2 fe |.V".e.<.4....b..| -00000020 29 4b 0c 14 b0 72 f5 c0 f8 2b 7e 1f 38 ad 68 7e |)K...r...+~.8.h~| -00000030 37 c3 fb 26 5a 5b 42 39 83 33 c0 |7..&Z[B9.3.| +00000000 14 03 01 00 01 01 16 03 01 00 30 d1 2e 43 5c f7 |..........0..C\.| +00000010 fc 5f 96 b7 e6 84 60 08 aa b3 22 d1 d9 e2 f3 4d |._....`..."....M| +00000020 c8 44 62 9b fa 0e 18 7c 84 fe 1e 75 09 4a f4 94 |.Db....|...u.J..| +00000030 67 03 91 79 90 26 70 2d 0e 97 6a |g..y.&p-..j| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 0e 54 7f 5d b9 f2 73 9d a5 49 25 |.... .T.]..s..I%| -00000010 c6 b9 03 1e fb 84 76 a9 69 ca 25 79 c3 a4 60 18 |......v.i.%y..`.| -00000020 94 ff 92 47 4f 17 03 01 00 20 cd 19 d2 cd 7d 7d |...GO.... ....}}| -00000030 3b a1 65 ee 4e a2 f2 02 55 02 28 54 28 92 c9 ec |;.e.N...U.(T(...| -00000040 db 59 f6 7d 2f 9e 7b 66 0e be 15 03 01 00 20 4f |.Y.}/.{f...... O| -00000050 ab cd 12 5b c4 f4 03 0e 57 03 3d f5 4e 09 8b 83 |...[....W.=.N...| -00000060 8b c6 9c c7 eb 30 8c f2 43 f6 10 30 14 80 c5 |.....0..C..0...| +00000000 17 03 01 00 20 c9 ce 68 cc e9 a7 f7 1f 3c 19 76 |.... ..h.....<.v| +00000010 4e a6 2d 64 86 4d 35 9b 5e 5b 8b c7 a1 15 d9 d4 |N.-d.M5.^[......| +00000020 5e 59 67 df 4d 17 03 01 00 20 26 09 76 e2 16 41 |^Yg.M.... &.v..A| +00000030 a3 7f 3e 8e cc 75 ab a0 cf e1 42 8d 3c 51 d4 bb |..>..u....B.>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 5d 02 00 00 59 03 01 6f 36 7b f5 f4 |....]...Y..o6{..| -00000010 3b 49 31 64 aa 42 a7 8c a2 4d 00 a7 9c b9 b6 9c |;I1d.B...M......| -00000020 0d 2f 09 81 e8 ab 74 77 11 fe 0b 20 e0 b9 92 4d |./....tw... ...M| -00000030 e2 70 fd 58 ec 58 02 f2 b3 44 d2 3d 7f c9 ad ca |.p.X.X...D.=....| -00000040 5c 78 fe f9 36 67 a8 b7 a8 0f 7a 1a c0 13 00 00 |\x..6g....z.....| +00000000 16 03 01 00 5d 02 00 00 59 03 01 97 c9 b8 e6 c1 |....]...Y.......| +00000010 0e b3 68 29 30 ed ff df a6 f3 cd b7 e0 80 a9 76 |..h)0..........v| +00000020 84 1b 45 bb 42 29 e0 c8 7f 52 4b 20 95 97 03 66 |..E.B)...RK ...f| +00000030 6b 45 44 7c 5d 4b 9e 47 fc 72 53 5d 3c 8a 28 6e |kED|]K.G.rS]<.(n| +00000040 bc 40 6d c3 96 67 f9 f2 72 ec 6d 0d c0 13 00 00 |.@m..g..r.m.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 01 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,36 +62,36 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 10 69 5f |............ .i_| -000002d0 db e5 a8 1f 14 81 0c c7 35 d4 3c 22 ee 17 a3 21 |........5.<"...!| -000002e0 47 9b e2 3c 5a f6 f5 46 b9 73 2a 7f 62 00 80 49 |G..ukv.........Mf| -00000340 57 70 1a 4c 21 27 7f c8 69 f4 f4 83 5c 44 32 b4 |Wp.L!'..i...\D2.| -00000350 73 18 a3 c4 4a c1 71 92 04 7a 49 49 15 25 05 a0 |s...J.q..zII.%..| -00000360 61 69 f8 38 4b 9f 92 96 f4 6b 6b 4b 96 60 45 16 |ai.8K....kkK.`E.| +000002c0 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 15 0b 17 |............ ...| +000002d0 fd fb 69 3e 44 71 3c 68 b2 6a 99 9e 8c 57 ba e8 |..i>Dq.$.`....9...Z| +00000300 12 2c c9 3e a7 db 25 ab 32 32 e4 79 9e 0a 9f 98 |.,.>..%.22.y....| +00000310 99 cd be b3 28 34 40 e1 78 3e 3d 20 35 74 79 7f |....(4@.x>= 5ty.| +00000320 f6 c5 5d 4c 54 30 1d 64 31 49 78 bd a2 cb 62 5a |..]LT0.d1Ix...bZ| +00000330 89 1a bf 65 bf 7f 1c ff 7d 61 6c 7d d2 76 8c 9e |...e....}al}.v..| +00000340 e4 80 56 7d 96 79 48 36 ca c0 99 db 9b ea 3a e7 |..V}.yH6......:.| +00000350 a7 fe cb ed d8 3b 34 8c be d5 ee be 59 d5 e2 5f |.....;4.....Y.._| +00000360 59 17 f3 57 29 eb c8 0e ed 1a 06 79 c0 3c 16 16 |Y..W)......y.<..| 00000370 03 01 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 e2 8b e2 aa 5a 35 c5 e5 68 ce f4 |....0....Z5..h..| -00000040 fa 51 3f 7b 3e 99 2f 21 b2 c6 b2 70 74 af ae ca |.Q?{>./!...pt...| -00000050 36 86 78 08 ea 8f 02 29 e6 a6 71 fa ad 7f c6 97 |6.x....)..q.....| -00000060 54 6f 88 a3 4b |To..K| +00000030 16 03 01 00 30 c6 d7 ad 2c 52 90 50 3c 50 ec 66 |....0...,R.P>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 af 26 01 47 8a |..........0.&.G.| -00000010 a3 08 b2 79 1c fe fa 91 e8 4b a6 e1 ad 8e 59 b7 |...y.....K....Y.| -00000020 ea 41 ee 3e 3a aa 2f f2 07 9e 0d 90 3d 6f 92 d5 |.A.>:./.....=o..| -00000030 72 92 ad ae ee c8 5d 48 a0 25 46 |r.....]H.%F| +00000000 14 03 01 00 01 01 16 03 01 00 30 8c a1 03 f1 fb |..........0.....| +00000010 fe f8 1b 43 7b fb 10 59 c3 ed b3 34 b9 74 e1 89 |...C{..Y...4.t..| +00000020 7f 5c 9b 81 b1 4f 13 bf 67 c5 87 92 31 96 7f e7 |.\...O..g...1...| +00000030 35 7b b0 da 2c 79 2e be 43 f4 cf |5{..,y..C..| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 29 2b 6a 75 2b 1b 94 f4 cb 80 14 |.... )+ju+......| -00000010 16 91 ec 08 77 5a 08 45 e7 51 2e a2 ec 03 f0 ca |....wZ.E.Q......| -00000020 35 88 20 3a 2e 17 03 01 00 20 59 0c 48 6f 66 8e |5. :..... Y.Hof.| -00000030 88 62 90 cc 33 39 62 ce 96 28 d0 2f 40 6e ed 14 |.b..39b..(./@n..| -00000040 94 72 88 d8 4a cb 73 24 a9 01 15 03 01 00 20 5c |.r..J.s$...... \| -00000050 8a 91 45 ed c9 38 e7 1d 71 02 b8 30 bf 24 0e 30 |..E..8..q..0.$.0| -00000060 6d fa 0a 4a 39 9f 56 b2 04 99 3e 67 bd bc d9 |m..J9.V...>g...| +00000000 17 03 01 00 20 61 e8 5a b2 15 88 f2 f9 e2 09 61 |.... a.Z.......a| +00000010 53 a5 7f 79 4b e8 c7 8d a9 5d 29 bf b9 0a 1d f7 |S..yK....]).....| +00000020 90 9f 3b 89 39 17 03 01 00 20 86 93 3b 08 7f 77 |..;.9.... ..;..w| +00000030 55 e5 51 06 ca 0e 80 96 9d 40 73 55 45 18 28 c7 |U.Q......@sUE.(.| +00000040 54 6a d8 15 d7 67 1e 4b 52 1e 15 03 01 00 20 56 |Tj...g.KR..... V| +00000050 d8 23 be 5a 8a a8 a4 8f 13 2f f0 34 24 90 96 87 |.#.Z...../.4$...| +00000060 59 48 3f 76 77 47 d5 eb 4d cb 80 00 bc 11 cf |YH?vwG..M......| diff --git a/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/crypto/tls/testdata/Client-TLSv10-RSA-RC4 index 8fce559c72b..c217b1112ac 100644 --- a/crypto/tls/testdata/Client-TLSv10-RSA-RC4 +++ b/crypto/tls/testdata/Client-TLSv10-RSA-RC4 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 55 02 00 00 51 03 01 9b 6a cd e3 08 |....U...Q...j...| -00000010 29 e7 32 d1 53 14 f5 4a cf b7 61 1a 90 d6 9a 73 |).2.S..J..a....s| -00000020 ad 48 2a 08 ce d7 d7 cb f8 25 b1 20 c1 24 61 85 |.H*......%. .$a.| -00000030 31 d2 81 5e 8e c8 31 40 56 36 79 af bb f7 90 d3 |1..^..1@V6y.....| -00000040 06 5e 4b 5a 62 50 c0 d5 89 7f 35 70 00 05 00 00 |.^KZbP....5p....| +00000000 16 03 01 00 55 02 00 00 51 03 01 6a dd d7 0d bb |....U...Q..j....| +00000010 bd b4 9c de 87 94 32 27 fa 4b 66 e0 8b 95 f2 11 |......2'.Kf.....| +00000020 a0 a5 30 15 34 6f 76 6b f7 23 ec 20 ef 7d 52 7d |..0.4ovk.#. .}R}| +00000030 2c 3b 30 1b f2 16 e7 8f b6 62 64 79 51 5b 31 36 |,;0......bdyQ[16| +00000040 b7 59 b1 f9 d5 26 d6 21 94 ff 7f bd 00 05 00 00 |.Y...&.!........| 00000050 09 ff 01 00 01 00 00 17 00 00 16 03 01 02 59 0b |..............Y.| 00000060 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 00000070 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| @@ -72,15 +73,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 01 00 01 |.Y(.....ia5.....| -00000090 01 16 03 01 00 24 b3 7b e6 d1 8f 79 04 e2 42 0f |.....$.{...y..B.| -000000a0 61 de d2 be 1e 4d 8f d4 6f 7e 2d 59 cf 23 ff 1e |a....M..o~-Y.#..| -000000b0 74 ea 2a 9c 7e e2 5b 23 05 2e |t.*.~.[#..| +00000090 01 16 03 01 00 24 0e 49 42 d7 a8 ca 08 09 a6 63 |.....$.IB......c| +000000a0 0f b1 4b 06 30 37 5e cb 3a c8 d6 ce f9 9c bf 2f |..K.07^.:....../| +000000b0 4a c1 c7 fb 2e 02 a6 b0 de ed |J.........| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 24 3c 4e 68 82 8f |..........$>> Flow 5 (client to server) -00000000 17 03 01 00 1a e0 a4 39 3c 9c 5c 8e 60 db 8e 5c |.......9<.\.`..\| -00000010 13 aa 60 4a 1c f0 71 1b f2 4d a9 f8 52 07 bd 15 |..`J..q..M..R...| -00000020 03 01 00 16 9e f3 0a 66 42 77 5a 75 74 18 85 f1 |.......fBwZut...| -00000030 3c fb ea d4 b8 76 6d eb 48 3d |<....vm.H=| +00000000 17 03 01 00 1a d3 71 0b 8e 0d d4 e0 06 04 e2 30 |......q........0| +00000010 59 2c fe 84 81 45 1c e4 59 90 b1 b1 11 85 cb 15 |Y,...E..Y.......| +00000020 03 01 00 16 ad 5d 98 96 4e 9d 83 af b0 50 64 77 |.....]..N....Pdw| +00000030 62 a1 2b 1a 63 59 16 9e 60 da |b.+.cY..`.| diff --git a/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES index 0ad2db05758..dbaefe8eb36 100644 --- a/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 5d 02 00 00 59 03 02 51 70 ac 24 75 |....]...Y..Qp.$u| -00000010 53 94 02 c6 20 8e 22 0d b2 79 30 3b ee a1 00 44 |S... ."..y0;...D| -00000020 f3 1c b8 a3 4c 51 c4 d9 30 95 d4 20 ca 82 67 4f |....LQ..0.. ..gO| -00000030 8c 13 5f c2 7e fc e0 0c 04 5c e2 9a c2 a3 02 a1 |.._.~....\......| -00000040 bc fa ca 16 38 83 2e 5a c1 75 19 67 c0 09 00 00 |....8..Z.u.g....| +00000000 16 03 02 00 5d 02 00 00 59 03 02 14 c4 6e 18 e9 |....]...Y....n..| +00000010 5b 74 0d 7f 05 01 75 e3 a3 af 90 f0 ea e3 a8 f0 |[t....u.........| +00000020 6e b5 7d 29 97 4d f3 7e e9 06 20 20 ba 37 13 9f |n.}).M.~.. .7..| +00000030 4e dd 10 6d 52 96 14 d0 93 3b 99 5b c2 cd f3 9c |N..mR....;.[....| +00000040 48 c1 12 78 c2 e5 e7 9d a1 d6 b4 da c0 09 00 00 |H..x............| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 02 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -57,38 +58,38 @@ 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| 00000270 95 12 07 8f 2a 16 03 02 00 b5 0c 00 00 b1 03 00 |....*...........| -00000280 1d 20 4a 31 cd 48 ea 05 09 8a 6d 78 c5 46 5d ea |. J1.H....mx.F].| -00000290 fb aa 62 79 17 70 31 5e 5a 95 c1 ce a9 52 3e 8e |..by.p1^Z....R>.| -000002a0 a1 7b 00 8b 30 81 88 02 42 01 e1 c6 99 40 d7 9f |.{..0...B....@..| -000002b0 15 41 f4 4f 54 5f 5d 14 bd a6 cc 18 6e 67 98 ab |.A.OT_].....ng..| -000002c0 6a 33 9d 54 68 94 2a 89 22 66 2d 20 97 e7 53 c9 |j3.Th.*."f- ..S.| -000002d0 f8 ee ad 64 46 6e 53 1d d6 57 55 6a 4c bc 37 1f |...dFnS..WUjL.7.| -000002e0 e7 9c c4 bb 23 cb af 27 2a 19 94 02 42 01 35 b4 |....#..'*...B.5.| -000002f0 a1 f0 c2 6d 34 f0 05 a7 25 9a 22 6c 3e 41 e7 a0 |...m4...%."l>A..| -00000300 1e 8f 5a 28 b1 5a 88 46 48 7e 40 93 f2 38 9d 33 |..Z(.Z.FH~@..8.3| -00000310 6b b5 92 ed 6d 44 07 03 c8 77 ee 3a 80 37 1e f9 |k...mD...w.:.7..| -00000320 4d 5c 2b 6d c5 15 07 b2 7c eb c5 f5 c5 14 dd 16 |M\+m....|.......| +00000280 1d 20 d1 90 13 d3 6d b1 e1 ec a3 e1 8b a1 d6 a6 |. ....m.........| +00000290 40 ac 8e cf 6e 42 06 7d a8 80 9a 9e a8 06 00 84 |@...nB.}........| +000002a0 69 1f 00 8b 30 81 88 02 42 01 b6 ba 66 1c de c4 |i...0...B...f...| +000002b0 8b a1 4a a7 0e f5 cb aa 5c 76 65 59 ba bb e2 7f |..J.....\veY....| +000002c0 a5 ee 91 26 77 40 e9 5d 25 73 5a d6 f9 b4 aa ac |...&w@.]%sZ.....| +000002d0 c8 bd 2b a4 95 b3 ef e0 c7 bb f1 d0 5e da 76 34 |..+.........^.v4| +000002e0 a4 34 5b 6c d6 c8 3b 13 b1 d0 12 02 42 01 e1 18 |.4[l..;.....B...| +000002f0 d5 90 79 c5 06 00 6b 7a 86 19 e0 2f 67 49 db 9e |..y...kz.../gI..| +00000300 4a 74 07 30 51 15 7b a1 01 89 9c 94 d8 17 18 a6 |Jt.0Q.{.........| +00000310 31 aa fb 4b 57 24 52 00 41 1d cc 36 89 6e b4 ed |1..KW$R.A..6.n..| +00000320 fc 23 33 63 dd 94 3b 40 6f f1 af d7 78 27 0c 16 |.#3c..;@o...x'..| 00000330 03 02 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) 00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| 00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 40 aa 15 c7 e0 2e f6 9e e8 aa 92 |.....@..........| -00000050 81 6d 83 8f 13 7e 7c d5 9f b9 bf ca 5d da fd 3c |.m...~|.....]..<| -00000060 ba c7 8e 8e 9a 93 86 21 49 15 04 9d b8 75 c1 fe |.......!I....u..| -00000070 5b a6 41 d5 46 |[.A.F| +00000040 00 00 00 00 00 bd f5 0b 25 31 b7 e6 3f 74 dc 39 |........%1..?t.9| +00000050 c8 a4 f5 3f 78 f5 6f 66 1b 59 53 51 40 d2 e1 14 |...?x.of.YSQ@...| +00000060 56 96 ea 1f 08 30 3f 66 ca e4 e4 a0 b5 9f 60 9b |V....0?f......`.| +00000070 f8 b0 c7 b8 79 |....y| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 40 ba a7 6d aa 40 |..........@..m.@| -00000010 b5 94 f8 d6 84 38 7c 19 7f b9 e9 8b 0f a8 db 4c |.....8|........L| -00000020 68 cf 1e d4 e0 b2 7c 78 80 76 18 c7 a5 cf 57 2d |h.....|x.v....W-| -00000030 1e 3d 17 b2 ce 44 93 76 38 91 4b d0 7f 09 00 2f |.=...D.v8.K..../| -00000040 c2 da c7 32 70 de fd cb a4 99 90 |...2p......| +00000000 14 03 02 00 01 01 16 03 02 00 40 68 2d 60 78 1b |..........@h-`x.| +00000010 a7 b8 28 3a 2b f5 cd b8 ef 4e 8e ab 3c d5 67 7b |..(:+....N..<.g{| +00000020 1f 29 9e 59 de ca 43 3a 4c 0c f5 70 43 cb 0b 40 |.).Y..C:L..pC..@| +00000030 69 a3 7c f7 1a 3b 48 2f b8 a2 7c b4 4a 03 36 2a |i.|..;H/..|.J.6*| +00000040 24 c9 78 9a 06 6e 18 2e 4a c0 54 |$.x..n..J.T| >>> Flow 5 (client to server) 00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 86 40 c2 e7 d4 56 43 6b e0 e4 96 |......@...VCk...| -00000020 41 74 2e b1 65 cd c6 93 06 71 f0 25 20 21 c5 1b |At..e....q.% !..| -00000030 d2 ea eb e4 06 15 03 02 00 30 00 00 00 00 00 00 |.........0......| -00000040 00 00 00 00 00 00 00 00 00 00 1e a9 c0 dc d8 23 |...............#| -00000050 f2 08 b0 c5 b2 2e 53 9b 23 50 8a 02 c6 41 9a 36 |......S.#P...A.6| -00000060 59 b1 23 d9 5e 91 45 cf 1b a1 |Y.#.^.E...| +00000010 00 00 00 00 00 f6 ff 38 da 12 09 78 fe de fb 0f |.......8...x....| +00000020 ea d3 5a d8 57 65 73 78 41 2d 0b 1b a4 8d f6 e7 |..Z.WesxA-......| +00000030 ed 58 97 c9 ea 15 03 02 00 30 00 00 00 00 00 00 |.X.......0......| +00000040 00 00 00 00 00 00 00 00 00 00 7d 4a 10 43 93 8a |..........}J.C..| +00000050 6d d2 50 34 92 22 24 f6 7a 9a c4 1f 57 e8 6d f8 |m.P4."$.z...W.m.| +00000060 74 c4 cb 8b e0 4d 99 dd ce 0a |t....M....| diff --git a/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES index 83c7d77102f..d0093da76c9 100644 --- a/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES +++ b/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 5d 02 00 00 59 03 02 79 2f de f0 f3 |....]...Y..y/...| -00000010 97 6a 5e e3 07 66 d9 f2 8b e9 be 1a 97 9f 6d c8 |.j^..f........m.| -00000020 9d b5 88 57 fc 8c 5d 7f d7 3e 34 20 e5 4c 51 33 |...W..]..>4 .LQ3| -00000030 52 23 a0 52 77 ca 41 4a 1b e4 22 fb 1c 82 f8 e4 |R#.Rw.AJ..".....| -00000040 aa 13 c2 1a ce cd d5 42 de b0 e9 10 c0 13 00 00 |.......B........| +00000000 16 03 02 00 5d 02 00 00 59 03 02 3d 12 00 a1 c0 |....]...Y..=....| +00000010 6f b2 13 96 d8 c3 b6 4e 81 60 03 60 fa 9a 4b 54 |o......N.`.`..KT| +00000020 a9 1d e3 e9 10 e6 8d 84 e3 af 76 20 7c 6d 5c 41 |..........v |m\A| +00000030 f6 19 49 92 b0 d2 1d 74 22 5d 6a 3f c6 5e 77 c0 |..I....t"]j?.^w.| +00000040 c4 bb 31 2d 62 8d 7b 5c 66 6d c4 94 c0 13 00 00 |..1-b.{\fm......| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 02 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,38 +62,38 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 02 00 aa 0c 00 00 a6 03 00 1d 20 ef 2a b0 |............ .*.| -000002d0 da 99 1f 17 dc 29 38 43 c2 72 18 b6 ea ad 8f e6 |.....)8C.r......| -000002e0 f2 d2 81 e5 f6 2e 6c 5a 95 89 10 14 34 00 80 11 |......lZ....4...| -000002f0 ff 56 fa 9e 9f 0c b9 a9 57 c4 2c cb a1 ce 70 ca |.V......W.,...p.| -00000300 94 bd 5e 54 0e eb da ce 1b 19 ee bc aa bb 9c 10 |..^T............| -00000310 f8 6e 59 48 82 5e fe 3c 2e 28 6d 8a 2f 08 ce df |.nYH.^.<.(m./...| -00000320 52 e2 07 a6 68 68 69 fc 2b d7 fd 28 ef 48 85 c9 |R...hhi.+..(.H..| -00000330 70 75 b4 f4 04 2f 39 69 ee 1a aa 14 c9 7b e0 f7 |pu.../9i.....{..| -00000340 bc 50 76 df 24 57 8b a4 ca 87 8a b5 ff c9 13 9e |.Pv.$W..........| -00000350 d3 9e 2b e1 d4 6f 0c ce 61 83 e9 38 51 04 2e 23 |..+..o..a..8Q..#| -00000360 b4 f8 90 f4 0f 45 93 34 14 f4 ca 4f 13 02 89 16 |.....E.4...O....| +000002c0 16 03 02 00 aa 0c 00 00 a6 03 00 1d 20 73 f2 57 |............ s.W| +000002d0 12 5a 50 bb 9d 2d 14 f0 ca ee c1 41 bf da 9e 8e |.ZP..-.....A....| +000002e0 d5 a9 25 c3 84 07 e7 5c 35 87 8b 70 3d 00 80 d3 |..%....\5..p=...| +000002f0 86 1b 82 48 5c 14 9b cf e4 a0 2b 24 bc 8c ad e9 |...H\.....+$....| +00000300 7c 1e 4f da c2 22 10 91 76 47 bc 9f 64 ca 1c 69 ||.O.."..vG..d..i| +00000310 77 c0 c7 2c 50 ea 1a 07 d0 8c ec da aa ed 82 9d |w..,P...........| +00000320 a5 6c d6 27 05 f8 24 19 f9 d4 b1 c6 e3 0f 49 6f |.l.'..$.......Io| +00000330 e4 47 25 9a 36 f1 d3 ed b1 b5 a0 cc 66 50 75 64 |.G%.6.......fPud| +00000340 97 ee 3c 65 84 1b 62 f8 1a 8f 02 5a d4 2c 49 b3 |..>> Flow 3 (client to server) 00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| 00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 34 fa 43 0a 6f 38 d0 80 5d a1 d6 |.....4.C.o8..]..| -00000050 61 c9 62 a9 b2 14 88 b4 7d b9 dc 20 93 11 27 37 |a.b.....}.. ..'7| -00000060 5a 2a 5b d4 10 54 75 23 8d 39 4a 5b 51 80 48 f2 |Z*[..Tu#.9J[Q.H.| -00000070 16 64 e5 90 38 |.d..8| +00000040 00 00 00 00 00 93 60 ad fa 30 93 3e 31 6d 2c 0c |......`..0.>1m,.| +00000050 21 3d 6a 53 b1 51 f9 a9 1f 74 ee 42 7a 90 8a 08 |!=jS.Q...t.Bz...| +00000060 9e a0 7f 42 19 c4 28 06 77 bb 32 c1 a0 0d ec 71 |...B..(.w.2....q| +00000070 4f 20 89 c1 7d |O ..}| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 40 f8 77 bf c0 dd |..........@.w...| -00000010 11 e1 3f 90 e0 1a c0 dc a6 6a b2 81 9b 1b 63 bc |..?......j....c.| -00000020 42 b6 23 b2 1f 95 36 38 56 f8 a4 e4 c1 c9 6f d2 |B.#...68V.....o.| -00000030 64 16 13 16 b7 25 53 ec a1 c2 94 de 8d ae 38 b9 |d....%S.......8.| -00000040 07 29 42 1d 16 3d fb 29 8b 76 15 |.)B..=.).v.| +00000000 14 03 02 00 01 01 16 03 02 00 40 fb 97 d9 4a c6 |..........@...J.| +00000010 10 21 6f 7b 77 ba e0 41 b2 50 d3 8c df 54 b1 9f |.!o{w..A.P...T..| +00000020 98 55 e7 0e fb bd 25 67 fb fb 5a 5c 86 b8 f0 17 |.U....%g..Z\....| +00000030 2b 56 b3 81 21 45 58 98 38 63 24 0a ec aa 17 55 |+V..!EX.8c$....U| +00000040 8c 46 67 a6 44 57 00 8d 49 83 28 |.Fg.DW..I.(| >>> Flow 5 (client to server) 00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 59 ac 45 2f 3f 3b d3 5d 73 08 85 |.....Y.E/?;.]s..| -00000020 9a 0e 99 a2 ad 8d 4e de 52 e9 5b 8b 76 71 5d 5e |......N.R.[.vq]^| -00000030 6b ec 05 24 a5 15 03 02 00 30 00 00 00 00 00 00 |k..$.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 92 ce 2d b7 15 d2 |............-...| -00000050 3b c5 42 ad aa 73 a8 e0 ac 26 d2 e7 ef c7 a9 72 |;.B..s...&.....r| -00000060 75 96 5c 8c 2d 60 6e 57 bd ef |u.\.-`nW..| +00000010 00 00 00 00 00 e7 87 56 3d 84 0b 17 94 41 94 67 |.......V=....A.g| +00000020 48 ff 0f e4 2d a9 1c 7a 68 fc 42 36 17 27 b0 66 |H...-..zh.B6.'.f| +00000030 af 97 25 90 a2 15 03 02 00 30 00 00 00 00 00 00 |..%......0......| +00000040 00 00 00 00 00 00 00 00 00 00 55 a4 8a bc 52 98 |..........U...R.| +00000050 07 3a dd 7a dc 4f 2c 8d f2 1b f0 76 09 ca 88 36 |.:.z.O,....v...6| +00000060 d4 fa f9 f4 b7 2e ce 6e 26 82 |.......n&.| diff --git a/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/crypto/tls/testdata/Client-TLSv11-RSA-RC4 index dd58620c470..64b06a8f17a 100644 --- a/crypto/tls/testdata/Client-TLSv11-RSA-RC4 +++ b/crypto/tls/testdata/Client-TLSv11-RSA-RC4 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 55 02 00 00 51 03 02 42 bb c8 01 43 |....U...Q..B...C| -00000010 e4 f7 10 09 bf 35 a3 c2 d7 ca 60 a9 60 be 1d 00 |.....5....`.`...| -00000020 92 33 b6 3e 56 2b c2 f7 29 e3 f9 20 8c d7 b6 90 |.3.>V+..).. ....| -00000030 03 f5 8b 55 e9 81 47 5b 84 ec 19 bc 32 58 c6 30 |...U..G[....2X.0| -00000040 f1 79 ea 51 a2 18 cc c0 4e 8a 8e cb 00 05 00 00 |.y.Q....N.......| +00000000 16 03 02 00 55 02 00 00 51 03 02 3d a4 ea 71 81 |....U...Q..=..q.| +00000010 c9 47 24 2b 53 22 83 07 df 5a 9e 76 ef ca d8 1b |.G$+S"...Z.v....| +00000020 1f 16 15 cd 7e e4 62 93 1e 5d a7 20 9d ac ea 5a |....~.b..]. ...Z| +00000030 9e e3 7c 14 94 9d 1b 9e 2a 7b 2d 80 55 85 2f 9e |..|.....*{-.U./.| +00000040 ed 17 20 79 66 a2 6c 88 81 cb b0 79 00 05 00 00 |.. yf.l....y....| 00000050 09 ff 01 00 01 00 00 17 00 00 16 03 02 02 59 0b |..............Y.| 00000060 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 00000070 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| @@ -72,15 +73,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 02 00 01 |.Y(.....ia5.....| -00000090 01 16 03 02 00 24 a8 40 50 90 31 50 fc 5e d8 f5 |.....$.@P.1P.^..| -000000a0 64 7a a5 62 8d ad ce 03 34 c9 ab 16 31 45 bc 8b |dz.b....4...1E..| -000000b0 26 8b fa 38 7a 2e 60 42 86 46 |&..8z.`B.F| +00000090 01 16 03 02 00 24 30 52 7f 8a 5c 3a 31 65 87 8c |.....$0R..\:1e..| +000000a0 9e 31 8f b1 22 15 ed af 99 6c 19 47 46 fd e1 3b |.1.."....l.GF..;| +000000b0 b3 f4 3a 5b d8 e5 a6 1a 7c 5e |..:[....|^| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 24 83 1d 5a 04 90 |..........$..Z..| -00000010 1f 8d 07 46 39 1e 3c cf cb 06 45 f5 88 9e 68 5c |...F9.<...E...h\| -00000020 96 a0 06 47 43 21 20 ce 90 1f 24 49 52 30 59 |...GC! ...$IR0Y| +00000000 14 03 02 00 01 01 16 03 02 00 24 c1 5d da 6d 6e |..........$.].mn| +00000010 55 3e 70 a4 52 15 d9 ba 88 a1 b7 f0 40 71 09 fa |U>p.R.......@q..| +00000020 3f 00 6f 39 72 88 89 a1 3d cf 7a 7a 97 15 b7 |?.o9r...=.zz...| >>> Flow 5 (client to server) -00000000 17 03 02 00 1a f9 9f c2 32 02 96 87 95 4b ba 17 |........2....K..| -00000010 1f b9 af fe 6a 87 38 d4 d8 b4 f8 1d ad 05 00 15 |....j.8.........| -00000020 03 02 00 16 54 07 15 34 f4 c3 a2 3e 01 9e 00 cb |....T..4...>....| -00000030 83 f7 58 79 e2 dc a4 b8 15 e9 |..Xy......| +00000000 17 03 02 00 1a 56 ea a4 ed 0f 9d 98 3b 48 bc 76 |.....V......;H.v| +00000010 35 3f fb 78 92 d9 ce ef 53 b2 ef a6 13 9a 4c 15 |5?.x....S.....L.| +00000020 03 02 00 16 b5 41 d0 98 50 73 73 90 c0 fe ec 11 |.....A..Pss.....| +00000030 ec 98 d5 fb 02 c0 11 11 29 1c |........).| diff --git a/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 b/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 index d88acc95f9b..33e01c140b0 100644 --- a/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 +++ b/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 55 02 00 00 51 03 03 d1 5c 30 66 38 |....U...Q...\0f8| -00000010 84 89 85 fe b6 87 de 62 8e b5 86 18 16 f7 8f b0 |.......b........| -00000020 f2 00 09 e5 55 d7 10 a0 76 d8 58 20 23 7d ff 5f |....U...v.X #}._| -00000030 b4 b5 5b de b9 7a f9 d1 bc 90 ff 2c 1d d7 fe ed |..[..z.....,....| -00000040 2f 6e 29 d8 08 61 0b 9d cc 7d 64 6a 00 9c 00 00 |/n)..a...}dj....| +00000000 16 03 03 00 55 02 00 00 51 03 03 c5 da f3 88 41 |....U...Q......A| +00000010 ed 43 a7 4e 49 ad db 74 04 c6 fb c2 13 49 86 14 |.C.NI..t.....I..| +00000020 fd d0 e1 7a ab d3 df 65 62 c6 1f 20 29 1a 03 bf |...z...eb.. )...| +00000030 10 35 3c 58 36 fd 4d 7a 7d dc f1 fd be d0 c6 b5 |.5D..l.C.:...S.| -000000b0 a6 d3 5c f0 5b ca e8 6a c7 13 88 65 50 71 |..\.[..j...ePq| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 2c 46 |.....(........,F| +000000a0 31 d0 81 b9 6e 55 b0 5b 7b 15 a0 27 da e2 d7 71 |1...nU.[{..'...q| +000000b0 f4 d0 83 6c 98 d9 75 e2 f4 4c 61 0b fe 3c |...l..u..La..<| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 3f 30 36 77 c6 |..........(?06w.| -00000010 6d 4f 37 2c ac f1 c2 24 9d e1 3f 0c 51 64 12 67 |mO7,...$..?.Qd.g| -00000020 83 47 ec f1 b8 02 6d 11 11 b7 ec ab 09 26 41 ff |.G....m......&A.| -00000030 e8 32 05 |.2.| +00000000 14 03 03 00 01 01 16 03 03 00 28 e5 b5 71 5d e0 |..........(..q].| +00000010 c8 9a 75 4c 6e 72 4e a2 5f f9 b4 9f f4 40 a0 de |..uLnrN._....@..| +00000020 73 48 9c 01 f3 0b 78 91 5f 85 29 9c 51 dc 77 bc |sH....x._.).Q.w.| +00000030 c0 32 42 |.2B| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 af 3a 1e |..............:.| -00000010 98 3e 74 5f 66 64 eb 6c 88 36 33 f0 98 e8 46 e9 |.>t_fd.l.63...F.| -00000020 f1 2f 32 15 03 03 00 1a 00 00 00 00 00 00 00 02 |./2.............| -00000030 76 2b 83 08 46 7d 34 58 db e8 e8 e1 e2 cb ad 1e |v+..F}4X........| -00000040 e4 a5 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 9e 81 42 |...............B| +00000010 90 9e ab a2 29 b3 f7 a6 31 45 5f a4 2e d5 52 f7 |....)...1E_...R.| +00000020 72 8b 3b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |r.;.............| +00000030 96 5a f4 de 37 1b 2c f1 8d 90 91 17 6f 81 90 7f |.Z..7.,.....o...| +00000040 e7 9d |..| diff --git a/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 b/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 index 030cbc6f2be..b373f27aaeb 100644 --- a/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 +++ b/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 55 02 00 00 51 03 03 bd e7 e2 ea 28 |....U...Q......(| -00000010 09 0b 7f 30 b5 91 fd b4 91 d1 c3 b8 8f 25 38 88 |...0.........%8.| -00000020 62 28 5c 1d 14 1a 6a 50 7d 30 e8 20 c3 91 2d ea |b(\...jP}0. ..-.| -00000030 59 8d 1d 56 98 c9 02 c0 f1 98 94 a6 8c 2b f2 63 |Y..V.........+.c| -00000040 ed b9 97 36 c6 c6 32 97 9e 61 6c 3b 00 3c 00 00 |...6..2..al;.<..| +00000000 16 03 03 00 55 02 00 00 51 03 03 eb c3 6e 78 2e |....U...Q....nx.| +00000010 9f 47 ec 9d 0e bc 8d 49 d2 46 11 75 5e 50 a5 07 |.G.....I.F.u^P..| +00000020 0a 99 90 34 34 2d 81 75 1b f4 ca 20 fb 28 c1 8c |...44-.u... .(..| +00000030 55 27 36 be 4e d1 c7 ee e8 b3 2a eb 7a be f1 2a |U'6.N.....*.z..*| +00000040 fc 81 df d8 5b c2 1f 1e 7b 47 0f 06 00 3c 00 00 |....[...{G...<..| 00000050 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| 00000060 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 00000070 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| @@ -73,25 +74,25 @@ 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| 00000090 01 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 |.....P..........| -000000a0 00 00 00 00 00 00 f3 6e c5 65 29 75 22 fe 23 6f |.......n.e)u".#o| -000000b0 96 fa b3 8d 98 ac df bf 3a 23 ca 4f d9 52 95 3f |........:#.O.R.?| -000000c0 89 8b 61 cf d2 2d f3 14 31 9d 3a 6f a9 b5 7b 69 |..a..-..1.:o..{i| -000000d0 27 a6 2b 2d 43 6e 77 f1 cd 73 fa 80 7b bf 8a 1d |'.+-Cnw..s..{...| -000000e0 83 c5 9b 8c 0a 03 |......| +000000a0 00 00 00 00 00 00 ee 37 21 73 05 93 63 ca 4f 0e |.......7!s..c.O.| +000000b0 e2 29 7f 90 6f 3a aa 52 a0 e0 71 97 5f f9 66 cf |.)..o:.R..q._.f.| +000000c0 06 19 09 51 03 5f 2e 0c 57 26 42 15 ef 8f 4e a9 |...Q._..W&B...N.| +000000d0 c4 97 95 0a d1 ce 30 2c bf 7a 85 4b a9 d0 a9 e0 |......0,.z.K....| +000000e0 64 11 1a dc 48 1d |d...H.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 f6 93 f3 85 25 |..........P....%| -00000010 06 5c 47 ea d5 6e 90 05 21 91 9a 86 06 42 f6 54 |.\G..n..!....B.T| -00000020 25 4a 61 65 7e 19 c8 1a 58 52 06 81 df dd 19 fc |%Jae~...XR......| -00000030 bd 5a 82 ff ae 80 92 b3 3b 7d 89 c0 64 b1 36 e3 |.Z......;}..d.6.| -00000040 5c bb 2a 5b e8 6d 18 02 43 27 b5 57 bc 3f ab b1 |\.*[.m..C'.W.?..| -00000050 27 59 0e 6a d5 07 6a 66 ad 51 82 |'Y.j..jf.Q.| +00000000 14 03 03 00 01 01 16 03 03 00 50 58 d1 09 93 e9 |..........PX....| +00000010 97 c1 cc c3 db 1d 65 d8 97 35 c1 b4 3f 9f a0 00 |......e..5..?...| +00000020 9f 81 2a 81 61 b5 51 9f ec 15 94 d0 86 0f a1 70 |..*.a.Q........p| +00000030 e9 90 59 dd 16 d3 e7 33 21 b7 d8 6e 4b a8 fd fb |..Y....3!..nK...| +00000040 dd 98 78 95 16 44 f8 da bd e3 e2 3f f0 e1 d9 39 |..x..D.....?...9| +00000050 c0 2e 0d c4 fe a5 ac 41 66 2d f3 |.......Af-.| >>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 2a 8b 84 55 57 20 b8 4f 11 d2 cc |.....*..UW .O...| -00000020 5e a0 ef 1a f1 62 fc 59 38 14 30 0f e0 76 04 ca |^....b.Y8.0..v..| -00000030 eb c2 45 a4 75 12 e6 1a 16 fc d8 bd d4 f7 fd 6f |..E.u..........o| -00000040 f3 99 ca d6 41 15 03 03 00 40 00 00 00 00 00 00 |....A....@......| -00000050 00 00 00 00 00 00 00 00 00 00 8c 80 a8 e9 95 4c |...............L| -00000060 c9 fa 4d 9d 06 e5 d8 70 5f fa a9 44 24 15 f4 47 |..M....p_..D$..G| -00000070 5a 0a 24 55 a7 6a 04 1c 2a 39 80 fd 08 47 d7 08 |Z.$U.j..*9...G..| -00000080 41 8b 9d 46 74 cb 61 c6 84 84 |A..Ft.a...| +00000010 00 00 00 00 00 2f d9 4b fc 22 0f 20 dd 2c 20 83 |...../.K.". ., .| +00000020 bd f0 49 5b bc 57 55 bc fb 41 13 79 a7 19 4d e3 |..I[.WU..A.y..M.| +00000030 71 66 ce b5 77 35 9c 54 86 0e fc 21 d6 9e c4 66 |qf..w5.T...!...f| +00000040 ee 95 3f 0a d5 15 03 03 00 40 00 00 00 00 00 00 |..?......@......| +00000050 00 00 00 00 00 00 00 00 00 00 54 25 cd 1a 0a d4 |..........T%....| +00000060 7b a4 ce f1 62 c8 8f 62 af 93 8e 0e e8 fd ef 55 |{...b..b.......U| +00000070 1d 47 a4 ac 1c 80 25 6f c4 a2 51 11 84 e9 63 cb |.G....%o..Q...c.| +00000080 db d8 e6 bf 2c 89 4e 1a d4 11 |....,.N...| diff --git a/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 b/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 index 42454d52f3f..9920621be3b 100644 --- a/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 +++ b/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 55 02 00 00 51 03 03 a3 a8 ef 9d b3 |....U...Q.......| -00000010 36 14 00 fe 5b e4 07 77 e7 78 c8 b4 d8 96 8d 72 |6...[..w.x.....r| -00000020 c5 79 99 10 8f 6e ac e3 fd 99 ee 20 53 99 57 36 |.y...n..... S.W6| -00000030 7e 9b 89 a3 79 c7 57 c6 f6 c7 2c 66 0a 6b 48 a2 |~...y.W...,f.kH.| -00000040 06 87 54 2c 20 3d 65 b9 1c 93 fd a3 00 9d 00 00 |..T, =e.........| +00000000 16 03 03 00 55 02 00 00 51 03 03 9f 42 e3 1b 5f |....U...Q...B.._| +00000010 00 d9 00 0a a5 fa 6d 63 95 11 d2 5a ff 51 b0 f8 |......mc...Z.Q..| +00000020 bc a9 7f 18 3c 8d d7 38 d5 e8 2d 20 be 5b 08 a0 |....<..8..- .[..| +00000030 2f 7b 50 d9 06 0c bf 7c 2d cc f0 39 3a 90 e4 e7 |/{P....|-..9:...| +00000040 9c 27 9b 88 ea ff c0 51 f8 79 cd b9 00 9d 00 00 |.'.....Q.y......| 00000050 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| 00000060 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 00000070 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| @@ -72,17 +73,17 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| -00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 76 c9 |.....(........v.| -000000a0 1e 50 43 51 5e 4a b6 c8 98 33 8f 18 ac f3 fe 20 |.PCQ^J...3..... | -000000b0 09 76 7c 48 f7 e8 00 2c 3b e1 7e 2f 71 d5 |.v|H...,;.~/q.| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 0e dd |.....(..........| +000000a0 10 e6 7a dd b2 02 5c 0d 0c 73 b4 f1 a1 89 85 95 |..z...\..s......| +000000b0 91 a9 e4 7a 47 49 9a 52 96 77 93 0b cc 74 |...zGI.R.w...t| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 55 b2 34 a3 b7 |..........(U.4..| -00000010 18 a8 36 55 c4 ef 81 82 e4 41 9f 1a 42 2c 42 7e |..6U.....A..B,B~| -00000020 9b 59 c8 9d 3a 0b 59 a6 78 d0 ab 2f c4 e1 f7 2b |.Y..:.Y.x../...+| -00000030 9b ee 9f |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 72 c3 d3 ad 10 |..........(r....| +00000010 71 48 c4 32 9b 24 ac c0 a4 88 db 35 e9 be fe 34 |qH.2.$.....5...4| +00000020 ee 9a bb 5a a5 90 b6 ec 31 9a bc 4c 56 e2 e6 d5 |...Z....1..LV...| +00000030 f9 2b 93 |.+.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 ec ad 42 |...............B| -00000010 8a cf 39 ed 82 b7 70 9b 1a 29 4c 3e b7 f6 92 35 |..9...p..)L>...5| -00000020 12 e2 df 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| -00000030 81 d4 de 3c 03 a9 01 0e e7 64 ae 18 84 dd d3 6c |...<.....d.....l| -00000040 57 6a |Wj| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 ed af c7 |................| +00000010 74 44 64 5d e3 1b 0c d4 bd a1 7e 7e 87 10 8d bc |tDd]......~~....| +00000020 26 db e8 15 03 03 00 1a 00 00 00 00 00 00 00 02 |&...............| +00000030 42 6b 3e 59 c5 e4 e5 5b 53 0f fe d9 3f 0c 5c f0 |Bk>Y...[S...?.\.| +00000040 67 d5 |g.| diff --git a/crypto/tls/testdata/Client-TLSv12-ALPN b/crypto/tls/testdata/Client-TLSv12-ALPN index 9f3f4dc930e..6686f6e9c0f 100644 --- a/crypto/tls/testdata/Client-TLSv12-ALPN +++ b/crypto/tls/testdata/Client-TLSv12-ALPN @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 01 12 01 00 01 0e 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 2c 01 00 01 28 03 03 00 00 00 00 00 |....,...(.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,22 +7,24 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 93 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 ad 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 10 00 10 |................| -000000d0 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |...proto2.proto1| -000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| -000000f0 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 |&.$... /.}.G.bC.| -00000100 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| -00000110 90 99 5f 58 cb 3b 74 |.._X.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 10 00 10 00 0e 06 70 72 6f |.............pro| +000000f0 74 6f 32 06 70 72 6f 74 6f 31 00 2b 00 09 08 03 |to2.proto1.+....| +00000100 04 03 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 |........3.&.$...| +00000110 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)| +00000120 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;| +00000130 74 |t| >>> Flow 2 (server to client) -00000000 16 03 03 00 6a 02 00 00 66 03 03 71 ba 32 f4 08 |....j...f..q.2..| -00000010 31 23 ea 71 46 b6 f0 24 f9 80 c2 94 b8 13 f5 cc |1#.qF..$........| -00000020 6b 77 e5 46 f1 76 df a5 0c 56 6a 20 98 53 12 a3 |kw.F.v...Vj .S..| -00000030 d2 a6 97 45 36 11 e6 b6 b6 6e 0b b9 30 2d 65 c8 |...E6....n..0-e.| -00000040 47 c7 af 4c c5 a6 51 90 2f 77 db 8c cc a8 00 00 |G..L..Q./w......| +00000000 16 03 03 00 6a 02 00 00 66 03 03 37 57 f9 cb 6a |....j...f..7W..j| +00000010 dc 6c e2 4b 1d 74 93 8e e1 1a 05 e7 fd 8d 29 57 |.l.K.t........)W| +00000020 5e b4 fc 9a ba 7d df de 56 cc e7 20 57 f3 1a b0 |^....}..V.. W...| +00000030 20 cd ac a1 e3 93 b9 79 f5 1c ce d2 d1 24 da fc | ......y.....$..| +00000040 88 97 25 fb 36 72 75 bb cc a3 2a 79 cc a8 00 00 |..%.6ru...*y....| 00000050 1e ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................| 00000060 00 09 00 07 06 70 72 6f 74 6f 31 00 17 00 00 16 |.....proto1.....| 00000070 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 |...Y...U..R..O0.| @@ -63,31 +65,31 @@ 000002a0 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b |Cw.......@.a.Lr+| 000002b0 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 |...F..M...>...B.| 000002c0 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 |..=.`.\!.;......| -000002d0 00 ac 0c 00 00 a8 03 00 1d 20 76 16 ff 2a 83 9a |......... v..*..| -000002e0 07 b0 01 f6 1e 3e 4b c1 69 62 9b 00 38 35 c5 4f |.....>K.ib..85.O| -000002f0 d3 2c db 50 16 9d 26 b1 cc 28 08 04 00 80 56 73 |.,.P..&..(....Vs| -00000300 39 4d ab f4 68 92 14 6d d5 75 db 10 4b 0c a4 19 |9M..h..m.u..K...| -00000310 9e 67 42 d3 f8 3f 91 26 06 4d f9 34 9b ad 7c 85 |.gB..?.&.M.4..|.| -00000320 ec 11 34 43 dd 7d a8 5b 0f 59 54 ff a3 92 dc 7c |..4C.}.[.YT....|| -00000330 26 ee 07 0e cf bc e4 6a 1a da b9 d2 9a 62 bf de |&......j.....b..| -00000340 37 a6 68 e2 cd 21 8e 4e a3 66 ee e1 74 45 7d 64 |7.h..!.N.f..tE}d| -00000350 b2 d8 1d dc 6a cd 2a 86 9e 0d 76 a3 7b f2 49 11 |....j.*...v.{.I.| -00000360 ae ad a1 d4 f2 a9 e5 56 0e 2a 96 a5 f7 8b 74 d4 |.......V.*....t.| -00000370 78 e0 bc cc 95 a1 f1 76 0b 4b 37 ed 77 1b 16 03 |x......v.K7.w...| +000002d0 00 ac 0c 00 00 a8 03 00 1d 20 27 fd a6 7d 32 28 |......... '..}2(| +000002e0 d2 44 43 d5 2a 95 3b e2 7e 77 5a d2 66 87 4a 92 |.DC.*.;.~wZ.f.J.| +000002f0 12 56 ba 40 3e 09 43 b4 90 02 08 04 00 80 8b e9 |.V.@>.C.........| +00000300 93 0c 5e 72 b8 a8 49 1c c3 b7 fc 39 af 58 9c 3a |..^r..I....9.X.:| +00000310 27 b6 20 23 9a 5d 35 0e dd 21 da 1b be 34 32 23 |'. #.]5..!...42#| +00000320 76 2e c8 9e 3d c8 e5 9e cd 04 11 a9 be 97 52 53 |v...=.........RS| +00000330 81 b6 01 fc 60 5d 0d dd 0d ba 05 a6 15 3b 29 4e |....`].......;)N| +00000340 88 a0 69 b9 c2 46 d9 c2 6d 17 b2 d0 c0 ee de f9 |..i..F..m.......| +00000350 94 fe 25 31 66 df 72 7d 02 77 a6 2c a6 ad da eb |..%1f.r}.w.,....| +00000360 dc 4b ea d4 5b 0a d4 e6 c8 89 15 cf 3f 81 58 20 |.K..[.......?.X | +00000370 0f 83 2f e1 db a1 cc a7 e1 61 79 7d 14 4b 16 03 |../......ay}.K..| 00000380 03 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 aa 8c 9c ab fb ab ed 5b 2e 3e 4b |.... .......[.>K| -00000040 92 cd 18 dd ac ce af 1a b9 f2 df aa 7f a1 d2 ad |................| -00000050 0e 8a 67 03 3f |..g.?| +00000030 16 03 03 00 20 50 e7 36 59 68 f6 0f cd b0 cc ae |.... P.6Yh......| +00000040 bc 18 23 d3 c0 fb c9 41 49 91 ec 8f cd f0 69 84 |..#....AI.....i.| +00000050 49 3c 68 6e 05 |I>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 db cb 3a 73 0c |.......... ..:s.| -00000010 ab 16 44 41 5a 25 df f7 45 bf f0 70 c6 a8 4f bd |..DAZ%..E..p..O.| -00000020 50 99 fb 18 26 e7 cf 71 16 1a 96 |P...&..q...| +00000000 14 03 03 00 01 01 16 03 03 00 20 84 30 04 4f 3e |.......... .0.O>| +00000010 72 f6 d8 6a dc ae fb 55 82 69 8e a3 77 c2 1f 27 |r..j...U.i..w..'| +00000020 88 14 5b 8d 10 79 4c 6a 41 3e e5 |..[..yLjA>.| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 34 82 27 01 99 27 08 58 c4 aa 76 |.....4.'..'.X..v| -00000010 fe 34 9c 1f 99 ea 4c f8 a0 ef 96 15 03 03 00 12 |.4....L.........| -00000020 68 b8 da ac 77 d5 f7 95 9f 68 e0 d6 26 88 cd ef |h...w....h..&...| -00000030 31 d4 |1.| +00000000 17 03 03 00 16 03 a8 d7 eb 5d 79 60 d4 65 1d c1 |.........]y`.e..| +00000010 2b 32 b5 c3 fb b2 2f 10 83 4e 39 15 03 03 00 12 |+2..../..N9.....| +00000020 90 eb 89 fc e7 4c a2 94 02 33 b3 0e 72 6e bc 4e |.....L...3..rn.N| +00000030 d4 e7 |..| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA index b56ac9f0c4b..784e95f87e5 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 d4 19 2c 08 c6 |....]...Y....,..| -00000010 ef 32 88 79 a1 84 fc 79 38 62 b2 dd 4b a7 0b b3 |.2.y...y8b..K...| -00000020 d3 13 3d d4 f7 c7 4d d9 8b c6 8e 20 56 8e 90 3d |..=...M.... V..=| -00000030 2b 6e 2d cf 7e c1 c6 b0 e5 d8 d2 af 3a 06 88 c6 |+n-.~.......:...| -00000040 ed e7 18 76 ab 45 c5 76 47 67 95 ad c0 09 00 00 |...v.E.vGg......| +00000000 16 03 03 00 5d 02 00 00 59 03 03 4a 0b 4d 4a 05 |....]...Y..J.MJ.| +00000010 a0 5b ca 5d 65 4f f7 7e 82 3c 54 1d a3 42 64 7c |.[.]eO.~..;O....P.......| -000002c0 0d 89 bc 6c 01 93 45 ca b8 3c 09 cf b2 01 e9 99 |...l..E..<......| -000002d0 87 fb 1d ac 91 7f 77 a2 21 5e 07 5e 65 3b ec 31 |......w.!^.^e;.1| -000002e0 d7 b5 b9 1d 88 c8 82 f5 03 a9 37 e8 b9 02 42 01 |..........7...B.| -000002f0 78 c4 90 fb e3 7f 5a 7a 66 0a 44 f5 66 0e 1e ac |x.....Zzf.D.f...| -00000300 cb 53 c4 74 55 3a b8 b7 ec b3 f6 4c e1 a8 b6 cb |.S.tU:.....L....| -00000310 a1 e5 37 ac e2 17 e2 6c 8f 71 37 b0 f1 ca b8 1b |..7....l.q7.....| -00000320 df 91 16 a4 7f 31 b1 4f 3e e4 30 f0 5a 5e df 93 |.....1.O>.0.Z^..| -00000330 85 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |.....:...6...@..| +00000280 1d 20 b8 ef 9c cd 47 a4 e9 1e e6 02 d5 40 12 95 |. ....G......@..| +00000290 0e da 1d 8f 2a 4f a6 9f 95 f9 1a 2a 1c ce 3c 32 |....*O.....*..<2| +000002a0 2b 4e 04 03 00 8b 30 81 88 02 42 00 c2 7d 24 9c |+N....0...B..}$.| +000002b0 b8 9c b1 69 fc 53 e9 ae 2c 07 39 23 d3 56 c8 96 |...i.S..,.9#.V..| +000002c0 e1 5e a9 a6 6b 18 33 f0 f9 50 29 65 2e dd 2b df |.^..k.3..P)e..+.| +000002d0 4e 58 67 ee 85 b3 da 8d 28 a1 7a 9f 59 df ae 10 |NXg.....(.z.Y...| +000002e0 31 d2 1b 6b 59 6d b9 24 16 79 66 49 7c 02 42 00 |1..kYm.$.yfI|.B.| +000002f0 bd a3 f5 56 db 00 b1 27 63 79 cb 1b 40 b2 e9 90 |...V...'cy..@...| +00000300 26 9f 44 53 ff fb 68 59 10 42 56 f2 36 fc 96 6a |&.DS..hY.BV.6..j| +00000310 a0 37 0e a3 77 5e 4c 0d 7b b6 e3 b5 b5 5b 2e d8 |.7..w^L.{....[..| +00000320 6f 99 6b af 84 57 9c 14 35 aa 09 23 11 08 83 3a |o.k..W..5..#...:| +00000330 63 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |c....:...6...@..| 00000340 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| 00000350 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| 00000360 03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 00 |................| @@ -110,31 +111,31 @@ 00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| 00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 93 0f 00 |...._X.;t.......| -00000240 00 8f 04 03 00 8b 30 81 88 02 42 01 c9 2c e8 1f |......0...B..,..| -00000250 5b a0 97 0f 70 2d 46 e3 6e b4 4c 82 fc be df 05 |[...p-F.n.L.....| -00000260 09 b0 d7 e4 0a 06 71 66 d6 3b 3e b6 56 2c 22 c7 |......qf.;>.V,".| -00000270 7c 3a 63 5c 34 22 5b 3a 49 a2 97 f3 2f 58 e7 2a ||:c\4"[:I.../X.*| -00000280 cd f4 05 84 db 8b 0b 22 e3 50 1b e7 6d 02 42 01 |.......".P..m.B.| -00000290 fd 1e bc 64 8b 01 3f a0 f8 8b 41 be 4d 97 07 6c |...d..?...A.M..l| -000002a0 3b 09 74 d6 00 76 b3 a0 c0 d0 92 d0 78 24 d7 b2 |;.t..v......x$..| -000002b0 1f c0 86 90 59 3a fb a8 e1 f6 80 23 db f7 90 93 |....Y:.....#....| -000002c0 95 fd 37 14 8c 34 f3 07 10 f8 dd e3 66 28 1c b2 |..7..4......f(..| -000002d0 a0 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |...........@....| -000002e0 00 00 00 00 00 00 00 00 00 00 00 00 6c b8 ab 0b |............l...| -000002f0 c1 2d 2f 4e d2 25 14 96 24 c6 18 97 82 93 1c 1b |.-/N.%..$.......| -00000300 b4 ca 77 8b 17 7c cf 08 ca 06 e2 ef f3 97 6a 31 |..w..|........j1| -00000310 88 aa 46 a2 d3 7b 65 56 e2 77 72 df |..F..{eV.wr.| +00000240 00 8f 04 03 00 8b 30 81 88 02 42 01 dd bf fd e0 |......0...B.....| +00000250 db 99 16 0b f0 bc a9 4b 93 10 d9 59 06 d2 eb 30 |.......K...Y...0| +00000260 dc b1 44 69 1d 54 2d 9b b4 a4 c9 3a f8 d8 9d 2e |..Di.T-....:....| +00000270 36 71 3e ff aa 05 98 8a 27 00 dd 65 6a 15 b7 c9 |6q>.....'..ej...| +00000280 fe 1d 4d 45 02 58 09 4f 38 ea cd 88 3c 02 42 00 |..ME.X.O8...<.B.| +00000290 a6 27 a5 d7 e7 9e 66 7e f8 38 37 03 7b 6d df c4 |.'....f~.87.{m..| +000002a0 81 6a 59 af 5b c7 06 2e 57 e9 8f 8d 1f 9c 9d 94 |.jY.[...W.......| +000002b0 70 4c 74 ed 03 24 3d df 35 51 a1 76 a7 8f 9b 40 |pLt..$=.5Q.v...@| +000002c0 16 c6 4f 0e 49 95 34 20 22 dc 5c ce 1d c0 ed bf |..O.I.4 ".\.....| +000002d0 f4 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |...........@....| +000002e0 00 00 00 00 00 00 00 00 00 00 00 00 b7 d5 df bf |................| +000002f0 2b 32 a9 9e e4 78 40 84 ca c9 7d 54 4e 38 89 3b |+2...x@...}TN8.;| +00000300 0f 83 23 42 75 95 6e 4d 70 d4 b6 5a 1a 26 dd bb |..#Bu.nMp..Z.&..| +00000310 37 4a 85 88 ab 60 ba 3c 19 bd 02 79 |7J...`.<...y| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 b8 19 a7 e2 35 |..........@....5| -00000010 8a be 5f 4c 91 d2 db 3f f3 42 90 8e b5 7f ea f7 |.._L...?.B......| -00000020 52 3e 61 2f 4d ef 25 8d ce 82 77 22 05 6f 0d b6 |R>a/M.%...w".o..| -00000030 04 c1 f0 f0 a2 9d bf 80 a9 f5 e1 62 5c e2 30 ef |...........b\.0.| -00000040 83 e7 c5 78 de 8f 17 4e d3 57 dd |...x...N.W.| +00000000 14 03 03 00 01 01 16 03 03 00 40 07 8e 16 c5 c2 |..........@.....| +00000010 e1 e5 32 41 2d 8b 3c fb 2e 3e b2 84 89 56 4d b5 |..2A-.<..>...VM.| +00000020 1c bd 1e a5 11 a1 b0 18 29 ce eb 46 f8 11 ff dc |........)..F....| +00000030 c0 cc ed 5a 38 33 5a 8f 48 df bf e9 8e 09 be b0 |...Z83Z.H.......| +00000040 9d 70 85 f7 71 f5 1e 5c aa 6f 88 |.p..q..\.o.| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 cb 79 13 ea 9e 7a 63 8f 5a 2b 8c |......y...zc.Z+.| -00000020 3a f3 bb 7e dc ff d1 2c 4a a6 4a aa ad bf 44 b8 |:..~...,J.J...D.| -00000030 cb 67 ce 3d f0 15 03 03 00 30 00 00 00 00 00 00 |.g.=.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 f4 15 a0 f0 64 d1 |..............d.| -00000050 dd 5f 14 66 6c ce 51 95 bc b5 0b f8 4f 42 48 57 |._.fl.Q.....OBHW| -00000060 cf f3 09 62 75 0d 3e 64 64 e0 |...bu.>dd.| +00000010 00 00 00 00 00 37 b7 99 22 eb 67 a0 32 57 76 b5 |.....7..".g.2Wv.| +00000020 53 86 fc 5b 79 c5 4a 4f 3a 6b a9 0f d8 c8 30 de |S..[y.JO:k....0.| +00000030 0a 5b 9b af e2 15 03 03 00 30 00 00 00 00 00 00 |.[.......0......| +00000040 00 00 00 00 00 00 00 00 00 00 57 9c 4b ca 83 a3 |..........W.K...| +00000050 c0 3a 52 71 24 f5 b1 37 1e 4d c1 5a 2d 29 1c 90 |.:Rq$..7.M.Z-)..| +00000060 9b 96 cf 1e 07 39 f1 1b 03 2b |.....9...+| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA index 692092e34f9..c20bd95d7f3 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 ed c3 6f 59 34 |....]...Y....oY4| -00000010 78 33 49 00 68 50 1f a5 aa 93 45 9a 87 34 c4 4e |x3I.hP....E..4.N| -00000020 71 b0 ab 5e 43 f7 a1 5c 89 e8 2f 20 f7 42 d7 2a |q..^C..\../ .B.*| -00000030 a5 fe 16 76 ac 6f cf 20 1d a6 bc d5 9d 27 9d 81 |...v.o. .....'..| -00000040 80 b4 0d 4e 12 89 de 7b 7a 5b a0 2b c0 2f 00 00 |...N...{z[.+./..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 48 41 85 3e fc |....]...Y..HA.>.| +00000010 9f e7 b6 84 da fe 2f a7 1d e9 ba 12 4e a1 cf cb |....../.....N...| +00000020 9e f8 df 76 7c e7 29 c1 3b 9e 23 20 07 c9 55 c7 |...v|.).;.# ..U.| +00000030 0e 45 5c 26 17 94 b4 14 6b 58 39 27 43 4e dc 9b |.E\&....kX9'CN..| +00000040 65 30 0e f2 bd 59 d9 a2 a1 f3 0a 01 c0 2f 00 00 |e0...Y......./..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,18 +62,18 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 d9 02 16 |............ ...| -000002d0 ba b6 db c0 c6 65 6d fb b8 69 dc 04 1a 8d 4a 36 |.....em..i....J6| -000002e0 27 6b f0 53 c3 72 56 1a 99 07 0f b9 79 08 04 00 |'k.S.rV.....y...| -000002f0 80 5d c6 1e a2 20 7d ae 35 e6 20 2f ff 7a 7b 8d |.]... }.5. /.z{.| -00000300 3f fd 49 d4 ce 26 f7 d0 c2 51 2a 42 03 26 b7 30 |?.I..&...Q*B.&.0| -00000310 af 5f 7d 34 1d 7d 37 ef 8a 1c e6 be 19 99 f1 30 |._}4.}7........0| -00000320 2e 26 6d 7b 83 cd 6e 26 c4 03 f5 7a 30 8f bf e3 |.&m{..n&...z0...| -00000330 c1 64 da 43 fc f0 32 c9 a2 68 e4 97 d0 34 8a c4 |.d.C..2..h...4..| -00000340 fc f8 bb 61 ec df 69 f7 d0 d7 1e 19 c0 5b 21 86 |...a..i......[!.| -00000350 eb 79 93 46 3b 7a 50 83 41 8b d3 7c 59 d5 34 8a |.y.F;zP.A..|Y.4.| -00000360 0c b5 70 e4 86 38 3a 6c 11 04 57 d6 94 c0 78 c7 |..p..8:l..W...x.| -00000370 91 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |.....:...6...@..| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 73 d3 a9 |............ s..| +000002d0 7e 93 32 e3 dd ad 1c b3 c1 ff 03 c2 b9 08 da 09 |~.2.............| +000002e0 d3 1b 67 95 9c 8c d1 05 12 2e 8b dc 7a 08 04 00 |..g.........z...| +000002f0 80 85 af 3b 06 67 b0 ab 07 70 21 02 b1 3a 89 40 |...;.g...p!..:.@| +00000300 d6 90 ef a5 5b 89 49 81 18 20 74 9f 7b dd 58 65 |....[.I.. t.{.Xe| +00000310 28 6f 2a f1 aa 3f 35 91 b9 88 79 27 a0 f3 e7 41 |(o*..?5...y'...A| +00000320 9a a5 77 be 55 5e 70 89 37 b6 4a 7b 3b 8c df ad |..w.U^p.7.J{;...| +00000330 47 cc ac 45 47 43 05 05 ad c9 7b d8 1d d6 a8 fa |G..EGC....{.....| +00000340 38 45 c3 54 35 0c 28 a1 29 be 1f 73 98 a6 02 01 |8E.T5.(.)..s....| +00000350 fb 9d 12 64 1a 9c f3 82 e5 3f f6 0c 20 67 59 72 |...d.....?.. gYr| +00000360 3f a7 59 4e ef b4 58 ba 49 4e c9 b6 ea 95 b2 b3 |?.YN..X.IN......| +00000370 78 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |x....:...6...@..| 00000380 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| 00000390 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| 000003a0 03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 00 |................| @@ -113,28 +114,28 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 93 0f 00 |...._X.;t.......| -00000240 00 8f 04 03 00 8b 30 81 88 02 42 01 a3 80 63 a4 |......0...B...c.| -00000250 49 60 35 5c 06 87 9f 7f ae 40 37 d0 64 58 b2 60 |I`5\.....@7.dX.`| -00000260 61 59 8b 6d a6 d9 55 67 81 f6 7e 9c de 40 69 00 |aY.m..Ug..~..@i.| -00000270 42 e1 2e 67 0d 48 cf 23 a7 28 f2 e0 9e 26 61 20 |B..g.H.#.(...&a | -00000280 4f 50 b6 e3 85 0b f5 f6 96 ec 03 32 35 02 42 01 |OP.........25.B.| -00000290 bd 3b 3e d6 03 98 b5 09 9a aa a9 73 1d 98 6a a5 |.;>........s..j.| -000002a0 29 ff e5 b3 f8 1f 58 2a a1 92 ea 2d 6d e9 71 d3 |).....X*...-m.q.| -000002b0 ce 04 46 ef d6 fb e4 5e e3 70 19 01 1a 22 85 70 |..F....^.p...".p| -000002c0 06 ec 15 bd ff ef af ed 2b 6d 00 97 cb 67 1f cb |........+m...g..| -000002d0 f6 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 |...........(....| -000002e0 00 00 00 00 80 da 31 59 19 74 39 ff a4 8c 30 1b |......1Y.t9...0.| -000002f0 25 fd 6b 25 57 ef 26 57 bd a1 df 90 4e d6 6a 47 |%.k%W.&W....N.jG| -00000300 96 08 54 92 |..T.| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 04 03 00 89 30 81 86 02 41 66 64 90 bc df |......0...Afd...| +00000250 a5 d0 19 89 2b ed fc a5 8f 7e 14 d0 9f a2 07 6b |....+....~.....k| +00000260 d3 09 07 46 f8 29 4d b5 6c 01 e5 2e 0d d8 a4 b9 |...F.)M.l.......| +00000270 1a 86 2f b1 10 4c 29 5b de e7 29 e6 b9 32 53 ca |../..L)[..)..2S.| +00000280 d0 fc 7b a1 82 6e 34 2f 11 7a 2b 98 02 41 74 a4 |..{..n4/.z+..At.| +00000290 51 21 0c 57 ac 99 d1 a3 8c 86 f6 f2 b8 66 b8 1f |Q!.W.........f..| +000002a0 2d db 49 1a c1 34 e6 02 fd ce 50 14 7c 9b a4 52 |-.I..4....P.|..R| +000002b0 17 bc 96 ab 11 5f 97 9a 7f be ab 26 f7 1f 2b cf |....._.....&..+.| +000002c0 30 f1 da 80 b5 82 a0 da 44 be c1 00 51 1d b4 14 |0.......D...Q...| +000002d0 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 00 |.........(......| +000002e0 00 00 39 c2 3d 4e 74 16 e2 8c 4b f9 11 38 94 12 |..9.=Nt...K..8..| +000002f0 8f d3 16 18 9b ad 41 ef c9 ed 56 7f e3 ed d7 e5 |......A...V.....| +00000300 0e 52 |.R| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 0e 1f ce 8a 46 |..........(....F| -00000010 77 28 6d e2 fc c4 e4 39 70 6b ab 6e 14 14 2a 34 |w(m....9pk.n..*4| -00000020 13 a0 5b c5 95 f5 fa a9 a2 f6 60 20 e3 1f c5 84 |..[.......` ....| -00000030 9c 00 5e |..^| +00000000 14 03 03 00 01 01 16 03 03 00 28 c0 9a 2a 35 ef |..........(..*5.| +00000010 fa 87 1f 74 0a e9 b7 ea 3c 1c ab 1c ce 6e bb 95 |...t....<....n..| +00000020 ef 92 f3 cb 07 c0 e6 af b1 2a 60 fb 09 2a d7 68 |.........*`..*.h| +00000030 27 b0 f1 |'..| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 88 d1 a4 |................| -00000010 c9 1b a6 a5 21 4d 93 e8 04 8b 3b 69 a9 2f bd 7d |....!M....;i./.}| -00000020 97 c1 3d 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..=.............| -00000030 ba 48 db 22 9e ae d8 a9 24 b7 a6 52 13 92 68 d6 |.H."....$..R..h.| -00000040 aa b5 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 b1 98 56 |...............V| +00000010 38 68 a7 d0 da c6 83 4b 00 31 40 d7 1e 81 35 1a |8h.....K.1@...5.| +00000020 2f e3 42 15 03 03 00 1a 00 00 00 00 00 00 00 02 |/.B.............| +00000030 1d 8f a1 cf 12 2f 53 37 4d 60 46 90 e2 db 97 ce |...../S7M`F.....| +00000040 3e 99 |>.| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 b/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 index edb433fefc5..9eb522b86b9 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 68 ad d5 4c 88 |....]...Y..h..L.| -00000010 60 b8 3b b4 ea e4 f2 55 7d 0f 90 d8 bd 55 b5 53 |`.;....U}....U.S| -00000020 49 6e f7 50 e4 05 70 a2 6d 9e a5 20 d1 0a e5 58 |In.P..p.m.. ...X| -00000030 38 f1 82 94 a7 c3 bf 77 60 d8 51 c2 c7 e9 8e d6 |8......w`.Q.....| -00000040 94 ee 4f 23 51 d3 2c 52 06 12 4b 4a cc a8 00 00 |..O#Q.,R..KJ....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 7f e3 92 d1 05 |....]...Y.......| +00000010 fd a2 f7 b4 24 f8 e6 e2 2f 15 51 f2 4b 72 12 59 |....$.../.Q.Kr.Y| +00000020 e6 af fe c9 0b 86 8b 53 a3 ce ff 20 68 97 1d e3 |.......S... h...| +00000030 6d 6c fb 67 78 05 ba fc 10 5b 83 87 8c 04 e9 57 |ml.gx....[.....W| +00000040 19 32 3f ee 88 a0 30 61 de 1c d2 2d cc a8 00 00 |.2?...0a...-....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,18 +62,18 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 4e 55 f3 |............ NU.| -000002d0 5f 83 c8 88 d4 f2 5c 75 6a ab 0e 25 df 12 ef f0 |_.....\uj..%....| -000002e0 ea e9 3e b4 4f 2c cd bb 43 5b 64 21 12 08 04 00 |..>.O,..C[d!....| -000002f0 80 84 5e ca 36 b2 fa d0 29 47 1c c2 de 4e 1d 81 |..^.6...)G...N..| -00000300 14 66 0a 26 6f 21 5f d5 b5 54 2e 37 f1 7e b1 90 |.f.&o!_..T.7.~..| -00000310 a0 57 ab 40 81 cf e5 77 29 23 54 fa 12 76 1a 4a |.W.@...w)#T..v.J| -00000320 66 c0 52 08 07 3c 3c 56 06 08 02 df 9f 75 75 5e |f.R..<| +000002d0 dd fc 30 52 61 80 f3 e8 7e e2 fb f8 03 ab e4 86 |..0Ra...~.......| +000002e0 bc 8b 69 5b f5 8c fd 4b fc 12 2e 99 1a 08 04 00 |..i[...K........| +000002f0 80 43 60 48 4c 88 e9 fc 78 36 5f a9 6a 61 54 7e |.C`HL...x6_.jaT~| +00000300 a8 a3 67 91 df ff 78 66 d6 b6 ce 95 26 af 8e ac |..g...xf....&...| +00000310 42 fa 95 e1 a3 c6 9b 73 bb 7b dc e6 aa ca 6f a0 |B......s.{....o.| +00000320 17 6b ee 50 ff d9 20 ed 11 c4 e5 81 23 1d 6b 02 |.k.P.. .....#.k.| +00000330 a8 e6 f6 ef fc 1f 69 9e c1 28 d9 bd 36 98 ad f6 |......i..(..6...| +00000340 f3 40 5a e8 a4 e9 3c 62 b2 8d 53 a1 88 06 e6 81 |.@Z...>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 10 cb 1b e5 55 |.......... ....U| -00000010 64 49 55 0a bf 25 e4 b0 d0 45 e1 47 b0 05 d0 f2 |dIU..%...E.G....| -00000020 41 b7 f4 6a 84 4e 6a 66 8d 0e 43 |A..j.Njf..C| +00000000 14 03 03 00 01 01 16 03 03 00 20 91 2c 24 55 e8 |.......... .,$U.| +00000010 70 9e 88 07 53 e1 60 9e 86 af 53 d4 21 d9 99 ad |p...S.`...S.!...| +00000020 3a 2b 83 b0 bc f7 93 5e 63 04 50 |:+.....^c.P| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 4a f3 ed 07 22 0d 7d 9b a6 a8 3c |.....J...".}...<| -00000010 88 58 f3 48 c2 f1 aa ea c7 cd 14 15 03 03 00 12 |.X.H............| -00000020 0b 1d 53 98 b3 69 99 e1 cd 4f 37 3c dc 63 17 9f |..S..i...O7<.c..| -00000030 00 7f |..| +00000000 17 03 03 00 16 e0 69 be 8e c5 4d 63 0e 77 88 42 |......i...Mc.w.B| +00000010 4e a8 e9 8f f4 c5 05 56 99 92 70 15 03 03 00 12 |N......V..p.....| +00000020 64 5c 05 8f 23 af e8 aa f6 76 1b b6 90 36 d9 d5 |d\..#....v...6..| +00000030 59 e6 |Y.| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 index c6673f6dc00..e9f6604b2f5 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 60 13 bb 4b ce |....]...Y..`..K.| -00000010 d6 49 3b b2 3a 0c d4 5a e8 25 26 67 41 fd dd 0f |.I;.:..Z.%&gA...| -00000020 62 ec c1 ab bc 58 92 67 9d 71 fd 20 20 4c ab 4d |b....X.g.q. L.M| -00000030 85 ce 87 49 68 8c cf 9c 2f 7b f9 2b 96 62 8a 75 |...Ih.../{.+.b.u| -00000040 c3 21 05 c6 ab b6 98 5e e7 e5 d8 4a c0 30 00 00 |.!.....^...J.0..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 bc b7 27 59 a9 |....]...Y....'Y.| +00000010 a7 ac ce 8b f5 5b 13 56 60 19 70 2a a7 f0 a2 ea |.....[.V`.p*....| +00000020 1a ce 27 2a 67 53 e0 5c 7e 5e 80 20 d5 c6 de 6d |..'*gS.\~^. ...m| +00000030 d1 3c 6d cb c9 49 77 00 cc 31 87 0a 86 45 06 70 |...| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 85 c8 0e |............ ...| -000002d0 fb 1e b3 4a ec c1 b2 3a b8 4e bb a1 ca 80 8e 13 |...J...:.N......| -000002e0 f5 08 b5 9a b8 3e c4 6c 23 cf 17 a0 31 08 04 00 |.....>.l#...1...| -000002f0 80 28 db ec 9d f9 f4 9a 06 12 8a 32 89 11 4a e5 |.(.........2..J.| -00000300 b6 68 98 21 ec f1 75 9c f9 28 bc b1 99 5b ec 77 |.h.!..u..(...[.w| -00000310 37 8b 6b 05 ad b3 10 de 24 05 84 a4 16 fe 1d 84 |7.k.....$.......| -00000320 af 5d 28 7d d7 bc de 2f 81 da a3 79 fb c0 a5 43 |.](}.../...y...C| -00000330 b6 3b 8d 90 30 00 80 98 16 83 ac 50 43 c7 3e 76 |.;..0......PC.>v| -00000340 c5 dc 85 c2 19 75 a6 90 f8 2f 71 40 d9 a0 73 7e |.....u.../q@..s~| -00000350 fe 3b 1c d7 66 73 0f f0 42 c5 00 b1 2b be 41 2b |.;..fs..B...+.A+| -00000360 40 da 8f b0 f1 9e b0 0a 83 23 04 80 fb 4c fe 7e |@........#...L.~| -00000370 b4 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |.....:...6...@..| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 8b ea d3 |............ ...| +000002d0 e4 1f c2 21 cb 32 99 00 d2 a9 a4 f3 e4 9a d7 6e |...!.2.........n| +000002e0 f0 6e 7c 45 ca 41 51 60 a3 31 61 f0 34 08 04 00 |.n|E.AQ`.1a.4...| +000002f0 80 96 62 58 0c b4 72 a7 49 1c b8 73 72 5a c7 ba |..bX..r.I..srZ..| +00000300 e2 fe dc a6 a4 54 3d 21 83 70 ab ef de d8 d8 db |.....T=!.p......| +00000310 82 56 22 4f 9d f6 04 c2 b6 f7 9d a0 41 88 53 c9 |.V"O........A.S.| +00000320 2b 57 80 71 a2 bd d7 84 b6 4b cd 65 3d c3 10 cb |+W.q.....K.e=...| +00000330 5d 89 03 af 46 d5 b0 39 b8 c8 2d 74 1b 46 8d 0d |]...F..9..-t.F..| +00000340 ca 13 30 34 54 10 ea ec 77 ca 84 a6 2c 88 68 d6 |..04T...w...,.h.| +00000350 69 e6 f3 95 aa 65 af 05 7d e0 c2 84 48 f5 fa ae |i....e..}...H...| +00000360 d5 90 2a 79 0c 45 c6 7d d3 b7 de 85 e8 b5 2b 68 |..*y.E.}......+h| +00000370 bf 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |.....:...6...@..| 00000380 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| 00000390 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| 000003a0 03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 00 |................| @@ -113,26 +114,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 41 83 55 9b 3c 8d 29 |.........A.U.<.)| -00000240 ed 6c 58 91 85 cb 9b 19 df 61 09 d0 d3 73 fb 2b |.lX......a...s.+| -00000250 3b 4b 4b bd 64 7e e6 53 87 cb 6d 2f 78 1c 67 cf |;KK.d~.S..m/x.g.| -00000260 13 21 e0 ec 1b d7 d8 aa 06 a0 0e d5 86 6f ba 1e |.!...........o..| -00000270 97 e2 8c 9b 86 e2 8a 4d 62 1a bd 35 0e 2d 63 18 |.......Mb..5.-c.| -00000280 a1 1f 7c ed fc 3b 89 c2 00 6d da 01 42 0a 47 95 |..|..;...m..B.G.| -00000290 12 8e 01 82 62 58 f9 96 eb a9 aa c3 f8 96 ec 20 |....bX......... | -000002a0 e1 65 a9 46 a8 af 4b 7c aa 29 ee 9c 48 18 b3 4a |.e.F..K|.)..H..J| -000002b0 00 7f 79 97 87 27 92 ca 45 14 03 03 00 01 01 16 |..y..'..E.......| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 da f3 01 f2 |...(............| -000002d0 76 e2 df 95 82 0d cc 0c 7e b0 cc 15 69 ba 8c 64 |v.......~...i..d| -000002e0 ac dc f3 45 58 a3 8f ed f0 2a 43 ce |...EX....*C.| +00000230 88 0f 00 00 84 08 04 00 80 48 ae 01 b6 4e e2 f0 |.........H...N..| +00000240 6b d9 58 e9 95 fb 93 56 10 8f 15 dc e8 3e c7 49 |k.X....V.....>.I| +00000250 b3 26 c2 06 91 4a 02 27 36 6b 21 cd aa 4a 62 6a |.&...J.'6k!..Jbj| +00000260 9d 44 6a b7 6c 16 d4 52 23 12 20 9d e5 5c 83 04 |.Dj.l..R#. ..\..| +00000270 d8 38 45 61 8b 30 5b 7b 6b 77 be 47 5a f8 fe 4d |.8Ea.0[{kw.GZ..M| +00000280 c8 e7 83 97 44 b4 fb 71 89 30 f2 cf d2 49 82 e8 |....D..q.0...I..| +00000290 d4 a8 73 86 44 29 30 17 7b b6 0e 4f 5f 6b 0c 33 |..s.D)0.{..O_k.3| +000002a0 43 7f 9b 84 a4 9b c6 30 18 ff 1b 85 a7 a9 17 23 |C......0.......#| +000002b0 2e 08 d3 57 10 af 49 95 2a 14 03 03 00 01 01 16 |...W..I.*.......| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 43 b8 4c 8a |...(........C.L.| +000002d0 84 1e 6c 41 02 fb b6 74 1e 4d 69 0d c0 f8 fc 8b |..lA...t.Mi.....| +000002e0 ce 64 53 95 40 c8 e8 52 31 5f a3 65 |.dS.@..R1_.e| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 e4 27 5e 80 00 |..........(.'^..| -00000010 ee db 03 4c 17 d1 9c bf f5 68 5f eb a6 fb 0c 3f |...L.....h_....?| -00000020 4f c4 38 84 3e c2 e9 f4 9b 06 39 5f 89 06 3a bd |O.8.>.....9_..:.| -00000030 77 db 25 |w.%| +00000000 14 03 03 00 01 01 16 03 03 00 28 04 f3 da a1 b9 |..........(.....| +00000010 b9 1a cf f3 a8 19 aa 23 12 65 8d 68 dc 37 09 9a |.......#.e.h.7..| +00000020 e4 0c cd e5 d4 3d cb 42 89 e4 ad 9e 49 34 de 05 |.....=.B....I4..| +00000030 74 f0 33 |t.3| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 2b 98 2b |.............+.+| -00000010 d6 dc d2 69 03 c9 0e 44 46 d1 5e d2 5a 14 89 7b |...i...DF.^.Z..{| -00000020 60 ab 62 15 03 03 00 1a 00 00 00 00 00 00 00 02 |`.b.............| -00000030 b9 7a 17 4b 10 5f 25 90 14 75 bb aa 42 de 7b 63 |.z.K._%..u..B.{c| -00000040 69 e8 |i.| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 00 33 c0 |..............3.| +00000010 3f 9c 56 3e 9b ed bb 5e 81 0c 4a 01 65 91 f5 da |?.V>...^..J.e...| +00000020 f6 4b 62 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.Kb.............| +00000030 55 6f 8d 18 50 1f aa 00 94 9b 79 26 f0 3e 0a c6 |Uo..P.....y&.>..| +00000040 45 b0 |E.| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA index 7b2a3631768..25120914e85 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 6d b7 f7 cf 1d |....]...Y..m....| -00000010 f9 c0 02 cb ee 90 23 93 41 8e 26 24 3e 74 31 ce |......#.A.&$>t1.| -00000020 4f 53 f8 9d 0f 94 02 b2 66 c9 87 20 d6 5c 35 52 |OS......f.. .\5R| -00000030 4b b1 f2 bb 2e 1d 95 ff 7d 83 f0 58 a8 0a ed b1 |K.......}..X....| -00000040 54 25 03 ca ea 7b 8d 1a 8f 9f 43 51 c0 09 00 00 |T%...{....CQ....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 80 e4 9b 9d a9 |....]...Y.......| +00000010 59 27 7f 44 b9 4b 90 31 c7 66 03 90 d6 9b ef 17 |Y'.D.K.1.f......| +00000020 f8 fb e5 63 04 68 f6 ce a1 a6 f4 20 cb 84 55 fa |...c.h..... ..U.| +00000030 41 77 48 0f 0a 5a 24 92 e3 59 b2 d9 91 0c 18 4a |AwH..Z$..Y.....J| +00000040 bf af ad db 64 db cb 57 d8 0b de 46 c0 09 00 00 |....d..W...F....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -57,17 +58,17 @@ 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| 00000270 95 12 07 8f 2a 16 03 03 00 b6 0c 00 00 b2 03 00 |....*...........| -00000280 1d 20 04 b4 79 b4 2c 1d 0f b3 4b ff 67 e7 24 88 |. ..y.,...K.g.$.| -00000290 d6 db 4f 1e 66 da 0e f2 89 5a 53 ed 4e ba ad 4c |..O.f....ZS.N..L| -000002a0 81 0a 04 03 00 8a 30 81 87 02 42 01 fb 16 53 43 |......0...B...SC| -000002b0 2b 86 61 0a 58 a0 68 c1 cd 2c ff ec 79 7f 83 fa |+.a.X.h..,..y...| -000002c0 cc 0b 24 9d 98 54 d0 dc 90 55 e1 b3 e6 48 69 1a |..$..T...U...Hi.| -000002d0 55 62 f4 da 8f 60 db f7 76 80 d5 4d 37 f6 43 49 |Ub...`..v..M7.CI| -000002e0 95 3d 96 f6 e2 fd a4 07 ae 24 8c fa bd 02 41 20 |.=.......$....A | -000002f0 a1 50 78 a3 dd 99 c0 cf 74 f1 c0 79 b1 13 9d bc |.Px.....t..y....| -00000300 0b 37 cf 7c 09 11 b8 a4 71 65 e8 be ff 3a b9 85 |.7.|....qe...:..| -00000310 cd b4 30 f8 1f d6 2e 83 96 6c 01 3e d2 00 a7 5b |..0......l.>...[| -00000320 23 c6 d0 69 eb 90 49 e3 46 ed 45 96 3b 07 d4 a8 |#..i..I.F.E.;...| +00000280 1d 20 2f 6b 4c 95 75 59 25 2f f7 fd b1 1f d2 9e |. /kL.uY%/......| +00000290 2f 38 5e 57 1a 7c 36 99 1e 11 4a 3f f7 13 5b 0b |/8^W.|6...J?..[.| +000002a0 90 33 04 03 00 8a 30 81 87 02 42 01 b4 34 3f d0 |.3....0...B..4?.| +000002b0 41 09 00 12 f4 79 20 f4 b7 80 5c d1 35 9d 8b d2 |A....y ...\.5...| +000002c0 fa c9 4a a9 44 6b 05 95 c5 a7 50 08 0d 73 66 3e |..J.Dk....P..sf>| +000002d0 dd 49 e4 a4 c6 c0 12 ca 0b 4a df bc c1 3e ec 88 |.I.......J...>..| +000002e0 ec 9a 0e 71 15 4d 45 98 04 3a 51 7a 67 02 41 15 |...q.ME..:Qzg.A.| +000002f0 17 de b0 5c 03 a5 74 0e 0f 2b 53 6e 55 17 73 b8 |...\..t..+SnU.s.| +00000300 ac 16 70 1a 95 f9 25 b1 fc 4b 9d c7 b1 f4 71 f6 |..p...%..K....q.| +00000310 86 2d 5b 74 9e d3 4e 1b 40 67 f4 a6 62 2e c8 4d |.-[t..N.@g..b..M| +00000320 66 f7 32 e9 05 df d5 b0 e8 1a b7 b1 48 c4 1c 91 |f.2.........H...| 00000330 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 |....:...6...@...| 00000340 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 |................| 00000350 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 |................| @@ -109,31 +110,31 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 3f 4a c2 4f 36 85 f0 |.........?J.O6..| -00000240 d0 c6 b6 8f f1 cc 45 c1 2f f2 c7 24 1e 0f 04 dc |......E./..$....| -00000250 f5 af 6e 38 eb aa a6 6f 36 f4 80 dd 78 78 a7 d4 |..n8...o6...xx..| -00000260 50 3a df e1 23 c4 3f 58 df 1a c0 1d 57 a5 46 3b |P:..#.?X....W.F;| -00000270 5d 09 ac 62 63 28 8a a2 b5 d4 9b 88 7c b9 4d b4 |]..bc(......|.M.| -00000280 66 b2 9d 53 6e 15 9c f2 9b c7 14 ca 19 7f 00 38 |f..Sn..........8| -00000290 81 a3 7b 44 e8 3d 6d 54 0f b3 81 fd 82 07 4d a1 |..{D.=mT......M.| -000002a0 3e 8c 30 34 cd 6e 55 96 58 bf 86 8b 9c f6 be 94 |>.04.nU.X.......| -000002b0 f4 a8 7e 4d 7f 03 07 7e 98 14 03 03 00 01 01 16 |..~M...~........| +00000230 88 0f 00 00 84 08 04 00 80 70 66 f2 ac fb f7 29 |.........pf....)| +00000240 15 31 a2 12 de 37 3f cc 97 74 5c 5b 7e 6d e4 f8 |.1...7?..t\[~m..| +00000250 b0 b3 3d 9c ee 32 bf d7 64 90 d7 af ad 8f 61 77 |..=..2..d.....aw| +00000260 f2 c0 7e 6f 91 1d 4e 95 92 3e ab 23 f0 ac d8 de |..~o..N..>.#....| +00000270 32 69 cd bc 04 4c d1 a3 77 7a af ac f0 64 41 aa |2i...L..wz...dA.| +00000280 a0 53 f0 89 89 a4 6f 1f 67 21 16 55 4e dc cb a8 |.S....o.g!.UN...| +00000290 12 7d cb a0 5c a9 48 48 d9 af 03 f0 75 ed 32 72 |.}..\.HH....u.2r| +000002a0 d5 da 34 a3 ea 82 08 8f 00 fc 7d 1d b8 11 ff f7 |..4.......}.....| +000002b0 09 52 a8 cc a8 66 b0 06 1e 14 03 03 00 01 01 16 |.R...f..........| 000002c0 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 |...@............| -000002d0 00 00 00 00 c7 88 1e 15 dd 36 31 22 0f 30 d1 4d |.........61".0.M| -000002e0 40 2e 3a dd 05 cc fd a8 d2 ea f8 d9 79 1d 07 46 |@.:.........y..F| -000002f0 2c 80 ab ab 54 3c 10 5a a7 79 d2 1c 16 18 94 eb |,...T<.Z.y......| -00000300 46 69 cc 03 |Fi..| +000002d0 00 00 00 00 9c 7d d4 9e 59 53 e7 66 64 63 9c cb |.....}..YS.fdc..| +000002e0 58 03 03 26 fe d9 15 eb 03 1c 8f a7 9c 5a 86 4a |X..&.........Z.J| +000002f0 6c 4e 06 4a 80 91 94 00 6f 7d 38 6a ea a3 68 df |lN.J....o}8j..h.| +00000300 17 08 14 ed |....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 9e 65 27 5b 92 |..........@.e'[.| -00000010 1e 2b 1a bc 81 ab 85 29 51 c1 38 04 b6 97 e5 4b |.+.....)Q.8....K| -00000020 b1 7d a5 e2 6d e7 b1 1a 33 6c f1 3d a4 9c de 2d |.}..m...3l.=...-| -00000030 b3 8a 01 da cc f1 d7 83 b1 1e 84 cb b7 e7 fe e6 |................| -00000040 26 83 b0 2d 6f a9 77 46 55 44 7a |&..-o.wFUDz| +00000000 14 03 03 00 01 01 16 03 03 00 40 7e 6d 15 90 c5 |..........@~m...| +00000010 99 96 ca bb 16 b5 5a 55 3e b0 ef 3f ab e5 b6 8c |......ZU>..?....| +00000020 51 1d 18 c7 c2 25 86 e0 db c1 d0 38 85 51 4e 8d |Q....%.....8.QN.| +00000030 37 51 92 cc d0 64 37 b7 67 7b 2c fc e7 1e 16 f6 |7Q...d7.g{,.....| +00000040 76 3a 94 48 68 eb dc cc cf 2a 4d |v:.Hh....*M| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 e2 55 06 b8 6f 63 c4 63 78 76 4b |......U..oc.cxvK| -00000020 c8 63 8b 4b c6 11 2c ff dc fc 20 f7 52 fe fa 5f |.c.K..,... .R.._| -00000030 e3 45 3a f2 a1 15 03 03 00 30 00 00 00 00 00 00 |.E:......0......| -00000040 00 00 00 00 00 00 00 00 00 00 0e cb 88 2f 1f be |............./..| -00000050 9c 76 4d db 75 7f eb 01 ae bd 76 28 07 41 49 6c |.vM.u.....v(.AIl| -00000060 4c 82 84 d5 fc d3 75 f4 4b 81 |L.....u.K.| +00000010 00 00 00 00 00 db 14 ae 78 62 50 37 42 b8 fc c6 |........xbP7B...| +00000020 f1 84 40 75 7c e4 3f 8a 57 b8 1c 12 4a 6f 11 f2 |..@u|.?.W...Jo..| +00000030 ba 1a a6 9b 20 15 03 03 00 30 00 00 00 00 00 00 |.... ....0......| +00000040 00 00 00 00 00 00 00 00 00 00 09 93 aa 80 fd b2 |................| +00000050 66 e2 83 0e f8 83 45 3d e1 39 06 5d a3 12 9e 12 |f.....E=.9.]....| +00000060 fd f5 cb 32 c4 3b ce 20 e4 10 |...2.;. ..| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA index 25fc245b650..3bfb4aaabd8 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 5f da ab 10 86 |....]...Y.._....| -00000010 4c 91 60 4c ec 28 20 d4 37 84 c4 d0 87 bb 9d a9 |L.`L.( .7.......| -00000020 5a c0 86 81 d9 91 38 5a ef 3f ae 20 ec 14 b6 de |Z.....8Z.?. ....| -00000030 b7 cf 59 09 43 dc 59 3f 74 89 10 f2 82 ea 60 46 |..Y.C.Y?t.....`F| -00000040 8f a3 6a 0f 61 0f 2d 66 24 c3 fb 7f c0 2f 00 00 |..j.a.-f$..../..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 c0 dd 18 ad 41 |....]...Y......A| +00000010 2b ee fd 45 1f c0 c1 10 75 a7 1d 80 74 3e 8e 66 |+..E....u...t>.f| +00000020 18 c8 64 c2 b4 89 4f 19 ff e0 0c 20 be c6 2a 8e |..d...O.... ..*.| +00000030 73 0a 1e 7a 2a d2 81 71 11 ba e9 de 02 0a aa 52 |s..z*..q.......R| +00000040 76 b7 43 a3 49 a0 81 24 9c 57 4c 26 c0 2f 00 00 |v.C.I..$.WL&./..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,18 +62,18 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2c c4 b9 |............ ,..| -000002d0 13 19 85 99 cb 09 f3 5c 3a a1 b2 16 ee 77 6a cd |.......\:....wj.| -000002e0 23 6c 08 00 7e 6b c0 67 a8 cd 8b 62 64 08 04 00 |#l..~k.g...bd...| -000002f0 80 90 74 bf ce f7 94 f1 94 b1 95 04 4a ab d6 08 |..t.........J...| -00000300 23 11 8d ce 4e 7b 36 ee 67 d2 26 af 11 0e 33 58 |#...N{6.g.&...3X| -00000310 12 cb e5 3b 5b 5c f3 d1 82 19 2e 55 6b 98 05 6e |...;[\.....Uk..n| -00000320 3c 5e 04 f5 3e df 76 c3 e5 46 e7 a6 bb f7 d4 d5 |<^..>.v..F......| -00000330 e8 fd 20 d3 ce 3e 9d a0 90 9a 10 52 a7 04 c9 e9 |.. ..>.....R....| -00000340 28 6f 3f ff e1 0a 10 d0 25 04 ea e4 84 4c b7 80 |(o?.....%....L..| -00000350 e4 fe a7 a6 da db cc b0 e0 62 80 10 fc 03 16 94 |.........b......| -00000360 f2 dd 0d 3f aa 11 45 af e3 e4 7b e6 bc d6 75 91 |...?..E...{...u.| -00000370 99 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |.....:...6...@..| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 5a f3 c3 |............ Z..| +000002d0 1b 34 9a 1a 01 68 65 fd 25 e5 e4 62 f4 17 d6 00 |.4...he.%..b....| +000002e0 88 ae 5e fa 6b ef 60 96 e9 96 1e 33 0f 08 04 00 |..^.k.`....3....| +000002f0 80 74 91 43 7a 3e 02 93 c6 6c 6d 36 86 2f 74 51 |.t.Cz>...lm6./tQ| +00000300 50 84 a2 0b 1c b4 90 71 72 2b f9 7d 35 2a a6 fc |P......qr+.}5*..| +00000310 56 b1 fa 36 e0 cb ea 5a 4e 89 71 3f 28 d3 fc 90 |V..6...ZN.q?(...| +00000320 de 21 0c 03 84 d9 23 78 b6 58 f2 03 02 27 48 f9 |.!....#x.X...'H.| +00000330 6d 6c 2b eb 62 36 47 66 55 fc d9 77 42 1e 9b 93 |ml+.b6GfU..wB...| +00000340 00 0f 5a 71 76 af 2c d9 b7 c3 6e e8 7a 64 34 0f |..Zqv.,...n.zd4.| +00000350 78 36 d7 cf a1 bb 3d 0a 23 64 c4 70 f0 78 8e 42 |x6....=.#d.p.x.B| +00000360 80 42 1f 0f 1d 7f c9 b6 7b 9c 2a 30 6c 7a ef 0c |.B......{.*0lz..| +00000370 2f 16 03 03 00 3a 0d 00 00 36 03 01 02 40 00 2e |/....:...6...@..| 00000380 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| 00000390 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| 000003a0 03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 00 |................| @@ -113,26 +114,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 4d c1 8a 3d 2b 1f a0 |.........M..=+..| -00000240 ad 6f 1c b6 44 7c cc 0d 21 6f e8 31 51 58 51 fe |.o..D|..!o.1QXQ.| -00000250 84 f3 41 40 12 48 29 0d 20 16 d1 6a 4b 38 0b c8 |..A@.H). ..jK8..| -00000260 b3 70 3f 4a ca 17 da 05 30 ec 6c 4f 55 e2 ee e5 |.p?J....0.lOU...| -00000270 9a 8c a7 9f c1 96 79 cf 53 b6 67 c8 cb 67 d3 23 |......y.S.g..g.#| -00000280 07 8a 3f ef df e5 e6 84 f6 5f 5e 23 57 89 cc 77 |..?......_^#W..w| -00000290 99 ed 3d 58 8a ec eb bb 64 62 d1 44 7f b6 45 85 |..=X....db.D..E.| -000002a0 89 06 90 56 48 98 8a 43 93 64 53 df 3a 8c b3 93 |...VH..C.dS.:...| -000002b0 91 81 7b 60 95 8f 99 99 eb 14 03 03 00 01 01 16 |..{`............| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 dd 93 96 02 |...(............| -000002d0 47 0e 1d 2f 6a 76 12 e5 56 53 8f 7f c1 cd f3 5e |G../jv..VS.....^| -000002e0 3c 94 35 1b fe d5 33 97 b2 5b a3 29 |<.5...3..[.)| +00000230 88 0f 00 00 84 08 04 00 80 56 a2 bb f3 05 94 90 |.........V......| +00000240 46 bc ef 79 ea 74 f9 a4 5c 27 59 dd 93 53 c3 9f |F..y.t..\'Y..S..| +00000250 07 b0 bf c1 e2 dc 39 b9 0d 63 62 d1 d0 88 65 e4 |......9..cb...e.| +00000260 2b 28 d3 ad b1 78 60 4c 0d a6 1f 2e a1 bc 36 81 |+(...x`L......6.| +00000270 31 f0 aa 0b 52 e6 04 69 ba 8a 9d c1 fd 25 d3 50 |1...R..i.....%.P| +00000280 43 5b ed fc 78 21 2b cc 13 f8 db f1 8b e7 57 d8 |C[..x!+.......W.| +00000290 59 f3 cf 54 ab d0 ea d6 8c 61 32 79 b8 be a6 c7 |Y..T.....a2y....| +000002a0 87 0a 35 88 70 f7 3f 2d bd 1b 7c 57 35 32 1b 81 |..5.p.?-..|W52..| +000002b0 87 08 e3 b0 1f a1 2b 13 fb 14 03 03 00 01 01 16 |......+.........| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 49 94 ed a1 |...(........I...| +000002d0 a3 13 e0 f4 20 2a 63 4d ef 24 d3 6c 8d 6c de b3 |.... *cM.$.l.l..| +000002e0 92 16 21 0d b0 6c 64 df 1b 32 ca dc |..!..ld..2..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 de 60 8a ea b5 |..........(.`...| -00000010 74 66 35 35 39 bb 62 ab 17 7d 91 c3 1a 5a e5 6c |tf559.b..}...Z.l| -00000020 49 14 c8 bc bd d6 b6 7e 2f 8e d4 40 5a ae ee 89 |I......~/..@Z...| -00000030 89 ae af |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 b9 2c 96 43 03 |..........(.,.C.| +00000010 f9 8c 28 34 4e 8b 58 ba d7 1a c4 87 d8 67 5c 0f |..(4N.X......g\.| +00000020 36 36 67 54 4e f4 6c 9c 0c 0e 1f df ca a3 8d ab |66gTN.l.........| +00000030 31 f2 84 |1..| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 3c 92 2d |.............<.-| -00000010 44 23 5b eb 34 dc 9a 4d c2 fe a7 88 cb 6f 8d 62 |D#[.4..M.....o.b| -00000020 4b 2a bf 15 03 03 00 1a 00 00 00 00 00 00 00 02 |K*..............| -00000030 90 82 82 54 5d 63 6e 8b 50 71 6e e8 fd 75 96 9e |...T]cn.Pqn..u..| -00000040 d0 0d |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 de 90 16 |................| +00000010 8e ec 2c 60 b8 a7 4f b6 26 8a c9 78 ff e0 73 19 |..,`..O.&..x..s.| +00000020 b3 01 c1 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 8a 4b 2c 4b 99 51 81 27 34 28 63 00 15 24 e1 47 |.K,K.Q.'4(c..$.G| +00000040 4a 2f |J/| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 index 6500aec8b01..b933f592bef 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 7b 21 bd ee 4b |....]...Y..{!..K| -00000010 af e3 88 cb 18 15 e5 f3 ef a5 a7 b3 a1 66 06 b2 |.............f..| -00000020 f1 cc d7 36 7e 18 d1 f6 2e 3e cd 20 34 09 01 9f |...6~....>. 4...| -00000030 c6 80 10 43 c1 ed e6 c1 29 1c ed ac 61 36 37 4f |...C....)...a67O| -00000040 8e 00 44 9d b9 cb 51 0b a2 9c 64 be c0 2f 00 00 |..D...Q...d../..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 0e 33 06 1f 9d |....]...Y...3...| +00000010 3d 0e 59 21 38 7d 4c ea a2 2a 2a c7 99 7b e9 bf |=.Y!8}L..**..{..| +00000020 61 e2 44 a1 10 5e 5d a1 e4 fd 90 20 c1 f0 1c 8e |a.D..^].... ....| +00000030 00 2f d9 a0 45 23 76 35 e0 01 2e 49 b8 4d b4 76 |./..E#v5...I.M.v| +00000040 08 65 3f cd 8b dc 80 ea fd 31 9f 47 c0 2f 00 00 |.e?......1.G./..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,18 +62,18 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 d3 22 bb |............ .".| -000002d0 c4 42 90 54 0a 43 f6 26 06 c1 ad 71 c8 82 ba 03 |.B.T.C.&...q....| -000002e0 9b cd be a4 a8 04 5a 30 69 ec b5 c9 79 04 01 00 |......Z0i...y...| -000002f0 80 ab c7 ca 24 9b db 7d 8c 81 c4 c4 46 49 2a 45 |....$..}....FI*E| -00000300 69 31 1b dc ef 01 ce 9f e4 da cf 6c 04 4c e3 4e |i1.........l.L.N| -00000310 16 84 05 fe 48 f4 21 60 fc d4 e1 6c 48 8c 87 2d |....H.!`...lH..-| -00000320 1f 56 2c ad 88 2b 5c 8d 4f 36 93 d6 a3 b1 32 4a |.V,..+\.O6....2J| -00000330 ef 0f e6 db 82 1c f2 ea 38 08 2a 62 8b a3 bd 4e |........8.*b...N| -00000340 8b 2a ae eb 0e e5 f1 88 ff 3c de f8 ed d7 c3 07 |.*.......<......| -00000350 05 92 bb e5 6d 15 23 c8 54 19 a6 cf d1 4f e2 b1 |....m.#.T....O..| -00000360 a3 4d ff 6f 22 32 5b 58 f7 58 c1 9f 58 59 b5 e2 |.M.o"2[X.X..XY..| -00000370 7b 16 03 03 00 0c 0d 00 00 08 01 01 00 02 04 01 |{...............| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 09 ce 63 |............ ..c| +000002d0 9c 52 37 83 ef 21 78 60 eb 8b dd 22 91 fb 34 4f |.R7..!x`..."..4O| +000002e0 ee 04 ef 48 75 2f 49 7e 3f 0b 00 62 15 04 01 00 |...Hu/I~?..b....| +000002f0 80 a0 11 99 d2 bc a9 fd 59 ad 38 20 bb 44 85 8e |........Y.8 .D..| +00000300 89 35 2e 42 ff a2 87 81 86 f5 e3 6c 9d 84 2a cf |.5.B.......l..*.| +00000310 0d cc 6a c0 ce 31 01 91 48 78 75 23 24 3e 3d 93 |..j..1..Hxu#$>=.| +00000320 bf ad c9 49 9d 63 66 cd 4b cc 92 0f 6d 64 2c 80 |...I.cf.K...md,.| +00000330 71 22 bf 6d 62 8e 8a f7 19 6f 50 2a 86 46 e4 46 |q".mb....oP*.F.F| +00000340 71 73 df 8c 25 84 6f 28 a7 8c bd 78 01 22 a2 91 |qs..%.o(...x."..| +00000350 f4 17 ef 88 55 9d d5 ac 42 5a 8a c8 7a 1b bf d1 |....U...BZ..z...| +00000360 d9 6d 15 42 b9 37 16 7b 2b 3c c7 58 99 da ab 98 |.m.B.7.{+<.X....| +00000370 f3 16 03 03 00 0c 0d 00 00 08 01 01 00 02 04 01 |................| 00000380 00 00 16 03 03 00 04 0e 00 00 00 |...........| >>> Flow 3 (client to server) 00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| @@ -110,26 +111,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 04 01 00 80 8f 22 b5 46 ab 82 02 |..........".F...| -00000240 f8 a8 f8 63 d9 0f eb d4 2b 8d 02 de ce 79 d5 a1 |...c....+....y..| -00000250 20 bb 70 7a b2 36 6a b5 52 81 f5 ea f7 23 b5 41 | .pz.6j.R....#.A| -00000260 86 35 90 cc 64 4a 68 7e e3 ae c1 97 32 3b c2 a9 |.5..dJh~....2;..| -00000270 e0 f0 07 14 63 d5 08 15 59 46 f5 ea a6 39 5c 98 |....c...YF...9\.| -00000280 39 7e 17 d8 74 ae 05 a3 f5 3a 71 74 e8 b4 c9 a4 |9~..t....:qt....| -00000290 1c 82 04 ca fe 5f 97 23 8a c1 f9 ce d1 5d 0e 81 |....._.#.....]..| -000002a0 da 5f e1 b6 76 80 3c cf 9f 19 79 cf 33 d0 0a fe |._..v.<...y.3...| -000002b0 19 fc 2d 9a bb 24 cd d4 79 14 03 03 00 01 01 16 |..-..$..y.......| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 28 78 b8 0b |...(........(x..| -000002d0 59 d8 a8 11 21 ed 45 74 02 00 50 33 42 b9 0a d2 |Y...!.Et..P3B...| -000002e0 8c 9c a3 45 6e b5 9d 3e 5b 30 a9 2e |...En..>[0..| +00000230 88 0f 00 00 84 04 01 00 80 01 83 0b 8b bf a3 50 |...............P| +00000240 03 89 e8 24 9b 9e 2e f5 7b 72 58 b1 b1 ba b2 64 |...$....{rX....d| +00000250 9f a9 e2 b4 00 78 79 50 ec 55 18 43 e5 c4 a4 76 |.....xyP.U.C...v| +00000260 c8 21 bc 7e e0 c4 2d 78 85 d7 33 ca d7 4d e0 f1 |.!.~..-x..3..M..| +00000270 cd 6d bd 17 2f a0 b9 39 93 29 ba d7 09 4f bb 08 |.m../..9.)...O..| +00000280 b0 b0 05 f1 83 de d0 db 39 f9 b4 34 a3 ca d3 76 |........9..4...v| +00000290 97 35 f6 ea cd 53 fe bb 94 99 30 e3 a2 0a 29 1a |.5...S....0...).| +000002a0 5f f4 28 0e 8c 80 fc 75 84 a4 e2 3a 29 a9 50 be |_.(....u...:).P.| +000002b0 11 99 bb a5 12 64 5c af 5f 14 03 03 00 01 01 16 |.....d\._.......| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 8e 51 58 0e |...(.........QX.| +000002d0 1a fd 8e 01 f1 6b 59 94 54 ab 00 be 45 8b 4c ae |.....kY.T...E.L.| +000002e0 70 c3 db 53 de 82 12 6c cb df 32 72 |p..S...l..2r| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 f8 f5 85 19 36 |..........(....6| -00000010 be 6e 58 45 66 04 c4 f9 e7 fd 50 55 3b 07 6c 50 |.nXEf.....PU;.lP| -00000020 16 8c 2e 72 cf be 78 0a 8a 82 91 ed c1 72 10 d3 |...r..x......r..| -00000030 cf 42 b5 |.B.| +00000000 14 03 03 00 01 01 16 03 03 00 28 7b 7f 81 c9 d7 |..........({....| +00000010 1d 3a 32 48 da 92 d6 9f 78 6e 2f d3 e9 7e 9f 12 |.:2H....xn/..~..| +00000020 9b 0b e1 00 e8 2f 4b 63 2c 3d 94 e4 f8 1e 06 7d |...../Kc,=.....}| +00000030 a7 7e 6a |.~j| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 53 4b a2 |.............SK.| -00000010 e4 5f 51 70 46 3d e3 41 28 8b 82 02 e2 27 8d eb |._QpF=.A(....'..| -00000020 42 65 7f 15 03 03 00 1a 00 00 00 00 00 00 00 02 |Be..............| -00000030 f3 31 ed 2c ca e5 13 e8 93 cd d7 51 4b c5 16 88 |.1.,.......QK...| -00000040 c0 a4 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 ee 21 1b |..............!.| +00000010 45 15 6a 0c 79 12 4d 79 d2 26 db fc e4 da 0f e4 |E.j.y.My.&......| +00000020 20 7e c7 15 03 03 00 1a 00 00 00 00 00 00 00 02 | ~..............| +00000030 2a 46 62 6b 5e c3 14 56 e1 fb d0 61 f5 e8 7b 2f |*Fbk^..V...a..{/| +00000040 cc fd |..| diff --git a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS index b4c5102535d..646026793f0 100644 --- a/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS +++ b/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 0d 73 c5 43 a1 |....]...Y...s.C.| -00000010 71 b6 21 da 7a f6 76 44 60 8a 84 ec 6b 1d 70 01 |q.!.z.vD`...k.p.| -00000020 d8 b2 29 48 db 5d ea da ea 79 bb 20 3f b9 66 fe |..)H.]...y. ?.f.| -00000030 73 db fc 90 18 3f ac e5 1f 5d 86 24 80 75 ec a3 |s....?...].$.u..| -00000040 c6 aa e9 05 c1 47 21 bd 30 f6 41 43 c0 2f 00 00 |.....G!.0.AC./..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 cd 47 5d a7 66 |....]...Y...G].f| +00000010 aa b1 e1 bd ed 83 bd 3d 4a b7 b2 08 b8 79 08 c5 |.......=J....y..| +00000020 22 7b 8d be fe 55 4c 2d b5 4c b9 20 13 26 2a e6 |"{...UL-.L. .&*.| +00000030 ab 60 4c 53 8c b7 27 c4 d5 12 ff 38 64 b1 a2 1d |.`LS..'....8d...| +00000040 4f a4 c7 28 53 95 01 8f 7e 4a 7b 02 c0 2f 00 00 |O..(S...~J{../..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 66 0b 00 02 62 00 02 5f 00 02 |......f...b.._..| 00000070 5c 30 82 02 58 30 82 01 8d a0 03 02 01 02 02 11 |\0..X0..........| @@ -62,17 +63,17 @@ 000002a0 fa b1 3f 14 11 89 66 79 d1 8e 88 0e 0b a0 9e 30 |..?...fy.......0| 000002b0 2a c0 67 ef ca 46 02 88 e9 53 81 22 69 22 97 ad |*.g..F...S."i"..| 000002c0 80 93 d4 f7 dd 70 14 24 d7 70 0a 46 a1 16 03 03 |.....p.$.p.F....| -000002d0 00 ac 0c 00 00 a8 03 00 1d 20 03 05 56 dd 40 c0 |......... ..V.@.| -000002e0 b6 4d 5a df 26 e7 4a f1 a8 47 ef af 12 6e 5f 01 |.MZ.&.J..G...n_.| -000002f0 2a 7a 19 1a 45 52 8c 47 d2 53 08 04 00 80 8a 6a |*z..ER.G.S.....j| -00000300 9d 8b 38 73 da 92 bc f6 05 79 90 af 7a 43 59 62 |..8s.....y..zCYb| -00000310 bc 97 b6 af ef ce 5f 59 07 81 93 bc c5 3c 5f f9 |......_Y.....<_.| -00000320 4e 04 45 74 5e cc 7a 6f 82 7a cf 86 0d 68 c9 35 |N.Et^.zo.z...h.5| -00000330 1d 62 f0 3c ee 77 b5 4c 3a 40 ec 89 fc 97 ff a6 |.b.<.w.L:@......| -00000340 34 13 8b bc 6b 83 92 e8 52 c5 c6 42 c9 25 ad 37 |4...k...R..B.%.7| -00000350 41 e7 5a 52 d8 0f 7d fd a8 9e 86 c6 1b b2 8b 50 |A.ZR..}........P| -00000360 2a 1c 15 56 00 d8 a8 85 86 05 28 7f a1 3e ba f2 |*..V......(..>..| -00000370 fe 92 07 c8 a4 4a 2a 5f d1 53 82 09 9c 65 16 03 |.....J*_.S...e..| +000002d0 00 ac 0c 00 00 a8 03 00 1d 20 a8 94 95 94 cc 16 |......... ......| +000002e0 f1 dc 11 b6 c5 52 b3 fe 95 4d 28 34 1f 2d 87 ec |.....R...M(4.-..| +000002f0 8d 56 51 0e 5b 92 03 f9 60 0d 08 04 00 80 09 3a |.VQ.[...`......:| +00000300 99 39 d8 3f 63 b4 86 12 ba ce e6 6d d6 22 aa d8 |.9.?c......m."..| +00000310 31 60 86 eb 48 cc c0 87 97 a5 0d c7 42 86 cc f8 |1`..H.......B...| +00000320 f7 f9 d5 1a 34 86 ec 41 02 08 99 c2 93 9b d1 b5 |....4..A........| +00000330 57 a4 84 3c a8 93 0a c9 f7 1e a1 33 07 ca 60 c4 |W..<.......3..`.| +00000340 4b 40 32 20 a6 22 3f 6d 4e 28 22 3b 52 70 9a 4d |K@2 ."?mN(";Rp.M| +00000350 fa 84 67 88 ba b5 0d 92 eb 23 94 90 00 e2 68 74 |..g......#....ht| +00000360 5f 13 a3 d4 2d fb 24 f2 32 09 b1 e3 63 15 39 b1 |_...-.$.2...c.9.| +00000370 9e 1e a6 61 fd 8d c6 cf 1f f7 f7 43 0c 64 16 03 |...a.......C.d..| 00000380 03 00 0c 0d 00 00 08 01 01 00 02 08 04 00 00 16 |................| 00000390 03 03 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) @@ -118,26 +119,26 @@ 00000270 10 00 00 21 20 2f e5 7d a3 47 cd 62 43 15 28 da |...! /.}.G.bC.(.| 00000280 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| 00000290 5f 58 cb 3b 74 16 03 03 00 88 0f 00 00 84 08 04 |_X.;t...........| -000002a0 00 80 2e 4c af b1 f2 9c de 14 92 81 c4 7d d1 2f |...L.........}./| -000002b0 a3 ba ba df 6f 26 da 2d 86 b4 1f 60 cd fe e7 c1 |....o&.-...`....| -000002c0 77 02 a5 58 3f 6a fc 1d ef 93 23 0a 9c c9 70 93 |w..X?j....#...p.| -000002d0 f8 0c 67 fd 58 83 96 85 62 da 31 e7 a6 78 9f 1c |..g.X...b.1..x..| -000002e0 dc 02 b3 b8 bc 05 26 92 e8 6a e7 3c db 5f 80 ee |......&..j.<._..| -000002f0 12 75 ff e6 36 36 e6 75 c2 77 d9 63 ef 60 89 db |.u..66.u.w.c.`..| -00000300 21 aa 27 85 11 9b 8c eb be a3 e3 34 0e 01 93 ca |!.'........4....| -00000310 a6 65 e3 cd 0f b8 b5 c6 f0 d7 15 69 db 4b 57 d2 |.e.........i.KW.| -00000320 05 0d 14 03 03 00 01 01 16 03 03 00 28 00 00 00 |............(...| -00000330 00 00 00 00 00 b5 09 a0 c4 55 89 df 8a 60 83 f3 |.........U...`..| -00000340 82 12 55 1d d5 50 11 81 74 0f cd b5 ed 9a 00 e7 |..U..P..t.......| -00000350 58 f7 65 0e 8d |X.e..| +000002a0 00 80 86 14 3f 28 40 db 2b 02 d6 56 d3 58 d0 77 |....?(@.+..V.X.w| +000002b0 58 f8 a3 25 1f 18 d1 9c 0a d2 56 09 32 59 34 db |X..%......V.2Y4.| +000002c0 d9 2e 0a bf b4 c2 0a 86 ee 6e 29 56 53 aa 82 11 |.........n)VS...| +000002d0 96 6d 86 29 7c 85 a4 71 56 04 71 5f e6 68 3f 3f |.m.)|..qV.q_.h??| +000002e0 71 54 13 a2 22 b4 3e 38 fa c2 96 a4 c4 ab 83 c6 |qT..".>8........| +000002f0 f5 ca 7a ea 2c 8d 62 4d 76 d6 db 9c f0 0e 8c 2a |..z.,.bMv......*| +00000300 38 2f 9d 24 34 f4 33 73 54 a2 44 9a e3 4c 1f a7 |8/.$4.3sT.D..L..| +00000310 ca 49 16 e8 35 29 29 d1 48 95 0a 38 19 64 4c e7 |.I..5)).H..8.dL.| +00000320 0d a5 14 03 03 00 01 01 16 03 03 00 28 00 00 00 |............(...| +00000330 00 00 00 00 00 09 7f fa f5 c5 e5 b1 46 7e 3d e2 |............F~=.| +00000340 d4 51 a7 b8 ae 0a 56 a3 8c 45 40 97 d4 c5 81 4e |.Q....V..E@....N| +00000350 6f 12 50 b3 f6 |o.P..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 3f eb 87 50 b0 |..........(?..P.| -00000010 ae c2 fd 68 30 95 94 61 1c 78 1e 60 3e 38 17 ef |...h0..a.x.`>8..| -00000020 ed 9b f1 10 26 5e 53 a3 8c 46 2e 6c 24 b2 ab a7 |....&^S..F.l$...| -00000030 6c f0 ea |l..| +00000000 14 03 03 00 01 01 16 03 03 00 28 0b 0d 27 bb 5f |..........(..'._| +00000010 c5 fa 62 08 8f 7a 24 65 90 bc de be 28 ae a4 e2 |..b..z$e....(...| +00000020 1f ac 18 7a 83 3e 90 bb 76 2f 73 ec 35 ca d3 e7 |...z.>..v/s.5...| +00000030 d8 25 7f |.%.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 fe de 40 |...............@| -00000010 52 50 79 da 5f 31 52 52 d8 96 04 35 86 92 03 0b |RPy._1RR...5....| -00000020 6f 5f 04 15 03 03 00 1a 00 00 00 00 00 00 00 02 |o_..............| -00000030 9c 85 24 b0 a9 17 24 cf 18 f6 ef f5 0d c6 77 6d |..$...$.......wm| -00000040 e0 b2 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 a7 07 a5 |................| +00000010 b5 4c 26 d0 d1 6b 52 10 8f 7c 3a 4c 31 ce 74 fa |.L&..kR..|:L1.t.| +00000020 4a c7 9b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |J...............| +00000030 22 22 5a b9 ef 4f 05 9f 2e 1e 9c 11 e1 6c 0b 1e |""Z..O.......l..| +00000040 bd 10 |..| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES index 774cb40e3dc..6268dbcc7a4 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 15 ed ca 52 59 |....]...Y.....RY| -00000010 e2 56 80 e2 f3 20 5b 7d 52 f3 67 1f 01 0d ad 30 |.V... [}R.g....0| -00000020 36 a6 43 c2 ed 5e 34 c5 24 89 e1 20 c7 4c 5d 06 |6.C..^4.$.. .L].| -00000030 01 7a 80 aa 84 0c 46 48 63 36 49 4a 9b 3f 8d ba |.z....FHc6IJ.?..| -00000040 78 1b cd f9 ef 03 df cd ee 2c b1 79 c0 09 00 00 |x........,.y....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 61 e9 cc eb 72 |....]...Y..a...r| +00000010 7c 11 18 0e 9d 6b 72 e9 be 84 f3 92 8d 5f e6 4c ||....kr......_.L| +00000020 ec 9e f0 00 ca 00 6f af 90 5b de 20 29 97 82 6d |......o..[. )..m| +00000030 57 ac 60 59 41 1d bb 29 b1 12 a4 ac 60 18 3b 51 |W.`YA..)....`.;Q| +00000040 af 5c e7 80 1a dc 9d 72 ed 3a 74 96 c0 09 00 00 |.\.....r.:t.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -56,39 +57,39 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 03 00 b6 0c 00 00 b2 03 00 |....*...........| -00000280 1d 20 b7 f5 92 bc 9b 4a f9 62 3f 46 b8 b0 33 56 |. .....J.b?F..3V| -00000290 1e 8d fc e9 68 af bf 67 9b a5 d0 9e a9 cc d9 65 |....h..g.......e| -000002a0 7e 41 04 03 00 8a 30 81 87 02 41 08 b2 fe 6e 40 |~A....0...A...n@| -000002b0 b7 5f 04 db eb 39 18 d5 e0 46 81 07 33 3a 29 fb |._...9...F..3:).| -000002c0 0b 19 76 ac 95 0d cd 4d a4 f0 99 df 6d d6 73 79 |..v....M....m.sy| -000002d0 ed 48 52 78 ea 7a 1d 4b b1 67 d6 fd 21 3b c9 9d |.HRx.z.K.g..!;..| -000002e0 89 67 b7 b9 8e cf 35 28 62 28 3f 0b 02 42 01 7e |.g....5(b(?..B.~| -000002f0 4c a5 af 5b ba 3b d6 38 3b 34 b7 0c 69 27 92 ce |L..[.;.8;4..i'..| -00000300 34 ba bb 0d f6 32 65 fe 3c c0 9c 9d 92 88 b4 11 |4....2e.<.......| -00000310 04 88 f5 b3 21 79 6c ed 6e f6 51 f5 e7 b1 3d 0d |....!yl.n.Q...=.| -00000320 bd d6 92 67 c8 90 71 7a db cc cc 21 64 44 22 d4 |...g..qz...!dD".| -00000330 16 03 03 00 04 0e 00 00 00 |.........| +00000270 95 12 07 8f 2a 16 03 03 00 b7 0c 00 00 b3 03 00 |....*...........| +00000280 1d 20 88 7d 69 d3 1b 2d b5 dd 4e 0a f4 98 f3 8c |. .}i..-..N.....| +00000290 42 d7 ee e2 7c 28 dc f2 75 ec b0 9e ca ad cb 21 |B...|(..u......!| +000002a0 59 34 04 03 00 8b 30 81 88 02 42 01 32 2c 84 f3 |Y4....0...B.2,..| +000002b0 d8 7c 05 58 ac d0 25 46 42 11 b4 7c 0a cb ee 83 |.|.X..%FB..|....| +000002c0 7f 68 36 b6 be f8 d2 0a 8d d7 bc 8a 95 d8 2d b3 |.h6...........-.| +000002d0 fa 87 56 ae 4c 01 3f bf 29 d1 81 c1 5d e9 f0 93 |..V.L.?.)...]...| +000002e0 f6 32 91 e7 da 18 84 dd 8d a4 94 3f 81 02 42 01 |.2.........?..B.| +000002f0 70 96 e1 3c c9 aa b8 72 8d 8e 13 68 00 50 65 9c |p..<...r...h.Pe.| +00000300 cf c6 1e 5f 5a d0 80 e8 8b ff 24 df a9 55 42 d9 |..._Z.....$..UB.| +00000310 75 83 67 d7 20 69 f1 29 2d 15 f4 83 f9 ff 3d c8 |u.g. i.)-.....=.| +00000320 0e 79 a9 3e 86 38 4a c5 a2 93 f1 47 a2 43 41 a5 |.y.>.8J....G.CA.| +00000330 bb 16 03 03 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 07 03 9e fa a4 84 27 17 b8 dd 53 |...........'...S| -00000050 12 4b 89 a1 47 98 22 e3 7b c8 d4 5c 18 bb 89 09 |.K..G.".{..\....| -00000060 29 3a b9 af d3 38 4a 40 76 d6 15 37 80 19 9c ce |):...8J@v..7....| -00000070 32 5b 94 89 2e |2[...| +00000040 00 00 00 00 00 84 08 13 72 05 4e a7 cb ac c1 40 |........r.N....@| +00000050 9e 31 9c a4 8f 7f f1 41 c6 63 19 39 3d d4 27 74 |.1.....A.c.9=.'t| +00000060 f9 5c 59 88 15 c3 e2 a7 6a 6f 6d fb 52 6f 94 36 |.\Y.....jom.Ro.6| +00000070 1e 8d 47 50 db |..GP.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 2d 53 b0 b0 c1 |..........@-S...| -00000010 05 78 e3 3c 5d 57 a5 04 9a 4b b9 f7 56 ce 5a 76 |.x.<]W...K..V.Zv| -00000020 84 4d f2 46 2e fc c2 9c ec 37 2b 4d 99 88 ab 30 |.M.F.....7+M...0| -00000030 1b 83 7d d8 72 bf e7 c7 f7 cf b8 13 54 d5 a2 a2 |..}.r.......T...| -00000040 dc 76 b3 01 a4 d0 a5 cc eb 66 29 |.v.......f)| +00000000 14 03 03 00 01 01 16 03 03 00 40 9f 65 82 54 e1 |..........@.e.T.| +00000010 50 68 92 33 d1 f2 a1 1d 95 81 e1 df c3 b2 4c 9b |Ph.3..........L.| +00000020 f4 8d ee b2 4b 43 2f e9 e3 af 60 ae d4 4c 7a 4b |....KC/...`..LzK| +00000030 f5 03 22 f0 11 58 de 4d ac 46 5a bf 98 da 01 1d |.."..X.M.FZ.....| +00000040 fa 19 ad a6 48 66 fa c1 25 4b a0 |....Hf..%K.| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 11 31 80 89 b8 32 e7 66 a6 eb c5 |......1...2.f...| -00000020 ca 4b f7 2b 47 73 e9 cd 9f 4e 9a 5e 3f 99 5a 29 |.K.+Gs...N.^?.Z)| -00000030 00 0d 4f 4e 93 15 03 03 00 30 00 00 00 00 00 00 |..ON.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 d9 18 f4 dd 64 64 |..............dd| -00000050 38 27 a7 96 d5 14 d1 b2 26 9c 14 96 54 2a cf d7 |8'......&...T*..| -00000060 4c d0 b6 c3 20 fe 33 73 78 e5 |L... .3sx.| +00000010 00 00 00 00 00 b3 26 24 39 5d 7c fc 25 23 ee fc |......&$9]|.%#..| +00000020 3a 6a 38 08 f5 bf 5e cc dc 34 83 1f 5e af b0 b4 |:j8...^..4..^...| +00000030 ee 34 fc f5 e1 15 03 03 00 30 00 00 00 00 00 00 |.4.......0......| +00000040 00 00 00 00 00 00 00 00 00 00 84 b2 cc 06 95 78 |...............x| +00000050 de 1d a0 cc d3 15 32 b7 89 74 8d 99 70 13 37 c3 |......2..t..p.7.| +00000060 e2 99 6e fe 8c 2d 69 77 cc 93 |..n..-iw..| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM index 86095340d40..e235f27b75f 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 e1 ed 2c 5d 15 |....]...Y....,].| -00000010 15 24 d2 e3 a0 58 fb 2f 89 a3 26 b1 c8 06 0f dc |.$...X./..&.....| -00000020 ef e1 a7 a4 81 4a 71 2c 1d a2 35 20 be ff 22 db |.....Jq,..5 ..".| -00000030 2d 33 1b 11 24 55 96 96 54 5f 62 c7 7f b5 ba 32 |-3..$U..T_b....2| -00000040 e7 e6 7c 11 68 f8 97 d1 17 f7 8f 4f c0 2b 00 00 |..|.h......O.+..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 ac 28 cc 34 03 |....]...Y...(.4.| +00000010 c8 91 48 22 79 a2 98 74 e4 55 df 72 6b 41 cb 40 |..H"y..t.U.rkA.@| +00000020 58 ba 04 93 e7 f3 1c 8e 0a 19 d1 20 98 93 cb 7c |X.......... ...|| +00000030 a3 57 a1 c7 ca 19 13 5c e1 ac c4 44 17 30 cb a3 |.W.....\...D.0..| +00000040 b2 83 81 90 82 1d 37 c3 71 ae b8 45 c0 2b 00 00 |......7.q..E.+..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -57,33 +58,33 @@ 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| 00000270 95 12 07 8f 2a 16 03 03 00 b6 0c 00 00 b2 03 00 |....*...........| -00000280 1d 20 74 55 23 1a ff ed d3 e7 95 30 ee ed 6d 77 |. tU#......0..mw| -00000290 57 83 fb 09 fc 81 70 69 d8 ae 38 1b e7 da 7f c6 |W.....pi..8.....| -000002a0 e4 01 04 03 00 8a 30 81 87 02 41 36 52 ca 91 b7 |......0...A6R...| -000002b0 a2 b2 31 91 98 96 65 92 67 a6 9c f2 75 8a 00 91 |..1...e.g...u...| -000002c0 8e 17 bd 22 d2 6c cb 16 0a fb 6b 27 08 3b f9 e4 |...".l....k'.;..| -000002d0 7c b5 21 45 60 4c c0 71 0b 28 46 d2 a8 a2 ad ad ||.!E`L.q.(F.....| -000002e0 51 fd bc 2e 40 7d 06 89 e7 b8 07 df 02 42 00 86 |Q...@}.......B..| -000002f0 83 4f 1d c1 c0 6d 3c f3 ed 24 47 70 65 e9 7c 5e |.O...m<..$Gpe.|^| -00000300 27 43 f0 05 b8 cd a4 34 ba 69 bc 81 7c fb b1 c3 |'C.....4.i..|...| -00000310 f8 bc 99 d6 90 15 8f db 21 fe 9f 18 10 23 75 6d |........!....#um| -00000320 22 b2 c6 f4 a5 60 80 31 06 a3 ad 33 88 c4 52 5d |"....`.1...3..R]| +00000280 1d 20 40 9c d1 ec 0a 11 08 c3 fa a0 33 80 00 62 |. @.........3..b| +00000290 5b 65 59 c6 4f 4e 32 8a 79 fc df 63 2f ee f6 59 |[eY.ON2.y..c/..Y| +000002a0 40 4a 04 03 00 8a 30 81 87 02 41 39 af 63 7a fa |@J....0...A9.cz.| +000002b0 dc e3 40 85 19 9d 1b 8f ca 55 26 e4 00 a1 f5 01 |..@......U&.....| +000002c0 73 e6 b5 6f ab bb c3 f3 b4 e0 c2 a1 33 37 ae ec |s..o........37..| +000002d0 e7 90 f6 dd b4 a4 c8 f1 3c 51 67 94 c1 ee d7 f3 |........>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 6b 3d 83 |....(........k=.| -00000040 88 db aa b0 62 30 8d 4a 6c b2 f1 14 d3 99 43 65 |....b0.Jl.....Ce| -00000050 4c ef 26 a4 ba 46 2f 75 9a 05 0c f2 91 |L.&..F/u.....| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 50 16 81 |....(........P..| +00000040 fe 51 5b ac de d7 31 1b 9a 09 4f 1e d4 de a4 af |.Q[...1...O.....| +00000050 c9 62 5d 38 85 23 84 8c ae 4f 55 5d 0d |.b]8.#...OU].| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 d5 c2 de 26 c1 |..........(...&.| -00000010 ed 28 f1 d8 81 b3 9a 4f 3d 82 ad 22 d0 2c 41 61 |.(.....O=..".,Aa| -00000020 8b 15 a3 72 01 94 44 ff 8f 01 c1 05 e6 84 56 0a |...r..D.......V.| -00000030 8b 1d c4 |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 d3 0d f6 53 0f |..........(...S.| +00000010 c8 3e f0 e6 c0 2c ed ec bc 8f cc 19 5e 33 30 69 |.>...,......^30i| +00000020 3c d9 55 8b e4 14 e2 0e 3a f9 89 39 fc a7 89 70 |<.U.....:..9...p| +00000030 58 16 44 |X.D| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 c7 7d a7 |..............}.| -00000010 c4 a5 a1 21 94 7a 23 bc 05 44 7d 4a 2f 16 dc 95 |...!.z#..D}J/...| -00000020 25 6e 17 15 03 03 00 1a 00 00 00 00 00 00 00 02 |%n..............| -00000030 77 fa b6 34 7e 60 77 f9 a5 09 d1 39 b0 1e 66 86 |w..4~`w....9..f.| -00000040 50 41 |PA| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 0b 26 61 |..............&a| +00000010 e6 d8 6a 6d db c6 2d 8a c3 8e f4 17 1a f7 8e f3 |..jm..-.........| +00000020 ce 04 ce 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 fa f7 0a 81 bb 8d 83 f3 82 05 ee 26 69 22 90 b2 |...........&i"..| +00000040 bb b1 |..| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 index ac5d07e69d6..f81845ab3d9 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 36 c3 50 72 b9 |....]...Y..6.Pr.| -00000010 0d e9 d9 76 1d 31 72 e6 61 ec 3e 13 93 d7 f1 52 |...v.1r.a.>....R| -00000020 a7 36 5c 16 9a cc c5 c0 da 7e f3 20 31 79 7a ec |.6\......~. 1yz.| -00000030 1d db f7 cd 0a fe b3 86 6f 43 12 f4 9d 19 16 51 |........oC.....Q| -00000040 e2 42 1b 94 43 13 71 67 2d 52 7a 86 c0 23 00 00 |.B..C.qg-Rz..#..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 be 62 2f ca 91 |....]...Y...b/..| +00000010 8b 79 1d ce e3 3f 2e 37 bc 74 da c8 7d de a5 85 |.y...?.7.t..}...| +00000020 58 c8 04 55 4e c6 51 f2 18 60 33 20 2f 33 8b c1 |X..UN.Q..`3 /3..| +00000030 b6 be 54 3e 3f 78 12 1b d9 d0 db 71 fa 0c ee f9 |..T>?x.....q....| +00000040 60 fb 49 08 a1 83 a4 f6 22 e8 dc 2c c0 23 00 00 |`.I....."..,.#..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -56,43 +57,43 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 03 00 b7 0c 00 00 b3 03 00 |....*...........| -00000280 1d 20 d2 2d 0f 11 29 eb b4 23 67 1c 40 84 7f 7e |. .-..)..#g.@..~| -00000290 cd 8c 3d c2 62 ed 9b 0f 08 01 5b a5 fd 86 31 c5 |..=.b.....[...1.| -000002a0 d2 76 04 03 00 8b 30 81 88 02 42 01 a4 ea c8 67 |.v....0...B....g| -000002b0 c0 0a 93 23 7c d9 41 17 ba 91 02 78 c7 16 28 85 |...#|.A....x..(.| -000002c0 b8 d6 5c ed ed 20 1e 8b 90 e0 19 db 67 72 7e d3 |..\.. ......gr~.| -000002d0 2c 2e 84 6a d7 bc b7 53 74 8b 1b ef a8 bc 39 d8 |,..j...St.....9.| -000002e0 e0 75 29 6b 1d 89 c3 12 c2 3c 51 25 84 02 42 01 |.u)k.....+| +000002b0 e8 b6 0b c9 76 80 60 6f 9a c5 4c 6e 7c d8 53 00 |....v.`o..Ln|.S.| +000002c0 56 c7 f9 37 36 32 2d dc 82 d8 0c 67 7a 96 5c 34 |V..762-....gz.\4| +000002d0 db 10 71 4e f4 29 e0 20 84 01 09 9a dc 74 76 39 |..qN.). .....tv9| +000002e0 63 e3 b2 c5 b4 7b cc 20 92 77 f1 3b a0 02 41 5d |c....{. .w.;..A]| +000002f0 36 ae 86 8c 27 7f 9e 0d 17 8e 16 48 20 2a 43 ac |6...'......H *C.| +00000300 d4 ce c6 9b 6a 95 47 5a 47 5c 13 b6 eb db 0b a6 |....j.GZG\......| +00000310 fa 23 fe 0c 76 e0 a9 b2 97 76 02 ff 68 3d 68 c5 |.#..v....v..h=h.| +00000320 17 08 54 25 1a 22 c0 a3 06 bd a3 f6 7c 68 07 9e |..T%."......|h..| +00000330 16 03 03 00 04 0e 00 00 00 |.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| -00000040 00 00 00 00 00 98 8d 15 68 8c 12 3e 4a 88 64 7c |........h..>J.d|| -00000050 69 46 25 16 66 20 d7 f5 7e 08 d8 9d c4 89 c1 cf |iF%.f ..~.......| -00000060 ac 86 b7 ce 3a 9c 95 0c 5d d1 a2 c2 bf fd 7c e1 |....:...].....|.| -00000070 b5 f4 04 7e 71 ae 3c fc d2 c1 2a ec 81 e4 62 a6 |...~q.<...*...b.| -00000080 e6 05 72 d8 9e |..r..| +00000040 00 00 00 00 00 27 1a a1 cf 9d f5 8f 91 e4 7f dc |.....'..........| +00000050 2f 81 3f 1e 3a c3 40 21 c2 6d dd dd 8f f6 9c 4b |/.?.:.@!.m.....K| +00000060 0b da 8d 10 f6 83 da 35 bb b9 a4 bf 2f 29 27 a5 |.......5..../)'.| +00000070 12 52 6a 74 6e 15 8d 82 cf 86 df f0 52 26 32 ca |.Rjtn.......R&2.| +00000080 02 91 8c 03 f7 |.....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 27 94 9b d3 f1 |..........P'....| -00000010 6c 59 bb fa b7 73 8b d6 fa b2 ca c1 0c d3 60 cf |lY...s........`.| -00000020 50 18 a6 6f 3d b3 46 a1 06 a2 b1 62 4c ea 88 2f |P..o=.F....bL../| -00000030 95 bc 35 6f 55 a6 8a 52 69 6c 5b a5 fc 94 2a b6 |..5oU..Ril[...*.| -00000040 27 7c d7 95 27 72 d4 c1 f2 f9 9c a5 b3 2a 85 52 |'|..'r.......*.R| -00000050 ae bf 14 52 54 51 6a fe a1 99 05 |...RTQj....| +00000000 14 03 03 00 01 01 16 03 03 00 50 1f 1c 35 9b 6c |..........P..5.l| +00000010 a8 9f 58 0d bf 0f db b5 91 c6 74 de b1 b7 68 b6 |..X.......t...h.| +00000020 05 0d 39 68 87 7d b3 b0 8b 86 15 67 ba 7e 54 0c |..9h.}.....g.~T.| +00000030 0d 4f 6e f3 ad d8 27 e8 1d fa 43 31 be 30 67 d2 |.On...'...C1.0g.| +00000040 bc 0a 30 37 78 3e 30 62 bf 81 2e 53 da b3 88 73 |..07x>0b...S...s| +00000050 17 42 79 ee ef 0e d3 3c 87 c8 85 |.By....<...| >>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 9b b4 f6 7e 49 48 09 cd 4f ed 22 |........~IH..O."| -00000020 68 db 19 94 ad af de d1 9b b6 bc f5 d6 7f c6 b2 |h...............| -00000030 ff b1 0e b4 0e dd 77 19 e8 9e ff 68 1a 04 fc e5 |......w....h....| -00000040 f2 3b 5b 34 aa 15 03 03 00 40 00 00 00 00 00 00 |.;[4.....@......| -00000050 00 00 00 00 00 00 00 00 00 00 f7 95 04 54 94 ff |.............T..| -00000060 f7 86 df 0a 2e 5b e9 54 fe 13 30 2a 97 f9 21 8e |.....[.T..0*..!.| -00000070 83 8b ba 86 77 67 92 33 5e a8 ea b7 64 65 63 59 |....wg.3^...decY| -00000080 44 2e 65 60 9a 0a 7c 78 97 a4 |D.e`..|x..| +00000010 00 00 00 00 00 2c 39 43 06 0a c3 81 10 24 e8 bb |.....,9C.....$..| +00000020 de b8 74 00 a9 a3 ab 9a 2a a7 8a 0e 62 b8 2a 23 |..t.....*...b.*#| +00000030 10 46 1b 76 dc a7 81 2d 37 2e e8 5f b5 75 5e 65 |.F.v...-7.._.u^e| +00000040 73 11 ef 71 16 15 03 03 00 40 00 00 00 00 00 00 |s..q.....@......| +00000050 00 00 00 00 00 00 00 00 00 00 a5 24 00 67 c6 ae |...........$.g..| +00000060 7f 05 91 ab 17 c9 ea eb 5a f8 8f 07 f3 e5 9b 9c |........Z.......| +00000070 20 41 63 21 69 3e f1 bb 66 7e 0b 3d c0 0a 14 b1 | Ac!i>..f~.=....| +00000080 a3 de 2e d9 10 23 37 84 4d 88 |.....#7.M.| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 index ad5fa501469..bf3f0192605 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 54 28 b4 3e d3 |....]...Y..T(.>.| -00000010 f8 21 2a 34 c9 6b 54 76 aa d2 cf 5e 07 7a aa e2 |.!*4.kTv...^.z..| -00000020 10 cb 3e ed 87 f4 3e 70 44 d0 35 20 6e b4 f0 71 |..>...>pD.5 n..q| -00000030 76 96 1e 2a 57 74 4b db 9a 11 0a af 06 ea 3b 20 |v..*WtK.......; | -00000040 a8 81 51 9d 41 ef f1 f9 23 87 18 cb c0 2c 00 00 |..Q.A...#....,..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 45 43 2c 7b 07 |....]...Y..EC,{.| +00000010 6e 76 10 6b f3 9c 7c 2e b8 c9 6b 8d a0 b6 7b be |nv.k..|...k...{.| +00000020 79 7a 52 ab 8d f8 c6 cb 00 f6 48 20 a3 a7 3c ca |yzR.......H ..<.| +00000030 d7 57 be c7 6e 45 d6 75 c1 70 e0 86 1e 58 14 a3 |.W..nE.u.p...X..| +00000040 b4 7d 78 2c ca 82 2f 38 b8 96 ef c4 c0 2c 00 00 |.}x,../8.....,..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -56,34 +57,34 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 03 00 b7 0c 00 00 b3 03 00 |....*...........| -00000280 1d 20 de df 32 23 35 b3 79 a9 49 c2 b3 ad 0c d6 |. ..2#5.y.I.....| -00000290 23 a6 6a 9b 0f e3 52 51 7b bc f2 79 00 c9 a4 a0 |#.j...RQ{..y....| -000002a0 94 02 04 03 00 8b 30 81 88 02 42 01 8c 12 91 28 |......0...B....(| -000002b0 d4 6d cd 39 62 75 9a e0 e5 dd ea 31 45 f5 cd 8b |.m.9bu.....1E...| -000002c0 28 82 14 f5 e9 61 0e 9d af 42 06 17 42 e9 24 1c |(....a...B..B.$.| -000002d0 2b 1a c8 77 e4 7a 82 2b b0 dd 28 3f 76 5d dd fd |+..w.z.+..(?v]..| -000002e0 20 53 87 e6 77 26 be 45 e4 6d 31 e3 bf 02 42 01 | S..w&.E.m1...B.| -000002f0 70 c5 97 3a e4 7b 80 2b 1b eb c9 b2 0a 79 92 2e |p..:.{.+.....y..| -00000300 3d b1 4d 13 69 d2 60 a9 fd e9 66 56 83 e4 f5 6a |=.M.i.`...fV...j| -00000310 ae cd 8b 94 9f 0b 70 81 b1 ed c6 0d 5f 33 42 04 |......p....._3B.| -00000320 3d f7 b6 d3 e9 09 b8 bf 43 8c 19 d5 7d 60 d6 a9 |=.......C...}`..| -00000330 f7 16 03 03 00 04 0e 00 00 00 |..........| +00000270 95 12 07 8f 2a 16 03 03 00 b5 0c 00 00 b1 03 00 |....*...........| +00000280 1d 20 2c 21 c0 1d 0f 62 0d 25 60 02 a2 5f 10 5b |. ,!...b.%`.._.[| +00000290 68 fb b8 74 a5 2f 33 d6 1e 3f 05 43 19 6d 1c 74 |h..t./3..?.C.m.t| +000002a0 ce 5b 04 03 00 89 30 81 86 02 41 4c 6b 04 c2 3f |.[....0...ALk..?| +000002b0 98 87 0d 54 5a d5 1f 4c 77 1b b6 e5 f8 1f 35 29 |...TZ..Lw.....5)| +000002c0 e9 72 13 34 ba f8 f9 b3 0f 49 ed b5 69 bd 03 3e |.r.4.....I..i..>| +000002d0 10 7d a5 0f 7a aa a6 c5 e0 48 24 2a 61 85 17 5d |.}..z....H$*a..]| +000002e0 ac 93 35 47 41 60 f6 3b d6 41 32 20 02 41 02 4b |..5GA`.;.A2 .A.K| +000002f0 b7 28 37 9d 5d f3 fe 87 7b 13 9a 71 b0 59 7b f0 |.(7.]...{..q.Y{.| +00000300 50 e2 87 aa 9a ef 0e e8 47 bd 85 60 d5 41 32 00 |P.......G..`.A2.| +00000310 aa 26 e4 f3 c9 4c 9d df 6c dc 6a de 2b fc 76 b2 |.&...L..l.j.+.v.| +00000320 99 28 41 1c d3 04 a2 e0 71 92 41 97 0a b3 4b 16 |.(A.....q.A...K.| +00000330 03 03 00 04 0e 00 00 00 |........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 a7 5d c9 |....(.........].| -00000040 e7 6b 78 13 ae 11 64 d0 e7 77 48 03 d4 cf b9 65 |.kx...d..wH....e| -00000050 7f 07 75 78 7f 3d ae a1 9a 0f fb cb 74 |..ux.=......t| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 5a b1 f1 |....(........Z..| +00000040 5a c2 32 50 dd 2b 6c 8a 0b de b7 04 cd 69 de 3a |Z.2P.+l......i.:| +00000050 45 3c 72 94 80 e2 f6 6c 66 98 c3 2d 4d |E>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 07 4e 69 71 66 |..........(.Niqf| -00000010 75 a0 bb b4 fd 86 8d 74 40 7e 0d e9 a5 95 d0 2d |u......t@~.....-| -00000020 ca eb 12 2f 7b 09 22 7c 8e bf da 97 18 d9 bd 74 |.../{."|.......t| -00000030 cd 08 6b |..k| +00000000 14 03 03 00 01 01 16 03 03 00 28 be d2 0b b0 a2 |..........(.....| +00000010 ac 18 1e dc 59 4f b4 85 be 3a 81 bd 73 51 47 35 |....YO...:..sQG5| +00000020 b3 2b b2 84 45 3a 08 11 a3 40 13 0e 5d ef 4b 26 |.+..E:...@..].K&| +00000030 9d e6 83 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 44 26 54 |.............D&T| -00000010 a3 37 94 7a 3d 93 6a 06 35 fe 9a d4 7b 54 ab d4 |.7.z=.j.5...{T..| -00000020 33 fd 93 15 03 03 00 1a 00 00 00 00 00 00 00 02 |3...............| -00000030 bf ff c7 9e 4b db ee a4 a2 b9 a5 91 cd 09 97 a2 |....K...........| -00000040 55 a5 |U.| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 0f 8d 3a |...............:| +00000010 5b dd b2 49 18 84 73 e7 a5 c0 46 c0 ad fa cc 44 |[..I..s...F....D| +00000020 60 0d 8c 15 03 03 00 1a 00 00 00 00 00 00 00 02 |`...............| +00000030 f6 4c c6 95 ff e5 01 3a 3b a9 46 23 f3 bc 24 29 |.L.....:;.F#..$)| +00000040 6d 52 |mR| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 index 9982121ef8c..db53e96a01e 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 @@ -1,24 +1,26 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 d4 01 00 00 d0 03 03 00 00 00 00 00 |................| +00000000 16 03 01 00 ee 01 00 00 ea 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a9 |................| -00000050 13 03 13 01 13 02 01 00 00 7f 00 0b 00 02 01 00 |................| +00000050 13 03 13 01 13 02 01 00 00 99 00 0b 00 02 01 00 |................| 00000060 ff 01 00 01 00 00 17 00 00 00 12 00 00 00 05 00 |................| 00000070 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 |................| -00000080 00 18 00 19 00 0d 00 1a 00 18 08 04 04 03 08 07 |................| -00000090 08 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01 |................| -000000a0 02 03 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| -000000b0 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 |3.&.$... /.}.G.b| -000000c0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -000000d0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| +00000080 00 18 00 19 00 0d 00 16 00 14 08 04 04 03 08 07 |................| +00000090 08 05 08 06 04 01 05 01 06 01 05 03 06 03 00 32 |...............2| +000000a0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000b0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| +000000c0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| +000000d0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| +000000e0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| +000000f0 cb 3b 74 |.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 4f ed 35 28 41 |....]...Y..O.5(A| -00000010 4a 0f a2 da 57 ef 60 69 32 00 a5 82 22 3d d9 ea |J...W.`i2..."=..| -00000020 36 28 20 31 e3 4a b6 d1 b6 b4 49 20 97 f3 45 59 |6( 1.J....I ..EY| -00000030 e7 9c f5 40 57 51 b8 f8 5a 8d f2 eb ce 83 18 2d |...@WQ..Z......-| -00000040 e3 28 55 6f 17 08 23 88 57 b1 a0 e4 cc a9 00 00 |.(Uo..#.W.......| +00000000 16 03 03 00 5d 02 00 00 59 03 03 74 9e c0 76 74 |....]...Y..t..vt| +00000010 c1 54 da a1 cf ad 75 4c fe 91 3b e2 06 e9 fb 1a |.T....uL..;.....| +00000020 9c 69 ee bf 30 1f 5c 0c 92 ca 58 20 a9 bb 64 3d |.i..0.\...X ..d=| +00000030 1e 8a 19 db 31 25 15 f2 65 5a 78 ad 7e d2 98 90 |....1%..eZx.~...| +00000040 8a 8b 0f 0e 77 53 db a2 93 b4 76 6d cc a9 00 00 |....wS....vm....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 |................| 00000070 04 30 82 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 |.0...0..b.....-G| @@ -53,32 +55,32 @@ 00000240 8c 25 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a |.%.3.......7z..z| 00000250 c9 86 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b |......i..|V..1x+| 00000260 e4 c7 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 |..x.....N6$1{j.9| -00000270 95 12 07 8f 2a 16 03 03 00 b7 0c 00 00 b3 03 00 |....*...........| -00000280 1d 20 64 49 59 eb a9 80 c3 0a 9e 13 f4 09 04 6b |. dIY..........k| -00000290 1f e5 3b 0b 77 84 fe 2e 1f ea 7e d4 64 2a 7f 3f |..;.w.....~.d*.?| -000002a0 dc 0f 04 03 00 8b 30 81 88 02 42 00 a4 62 9b d1 |......0...B..b..| -000002b0 ed 60 b7 2d 05 48 64 b6 94 3b a1 75 cb 41 78 e5 |.`.-.Hd..;.u.Ax.| -000002c0 e0 12 70 d9 90 4d c0 34 39 f3 52 13 75 4b fa 10 |..p..M.49.R.uK..| -000002d0 19 6f a6 2d b4 c3 8f 45 0c 7f 34 fb 82 01 e6 a1 |.o.-...E..4.....| -000002e0 be 73 72 3b e5 04 80 70 7d bd 4a f9 e5 02 42 01 |.sr;...p}.J...B.| -000002f0 69 3d 53 e9 8d 70 6d 07 84 7e 56 3f ce 53 b9 6c |i=S..pm..~V?.S.l| -00000300 43 0f 70 74 f1 52 ce d4 95 55 13 8c 07 e7 20 d7 |C.pt.R...U.... .| -00000310 61 2e b7 f4 5b 34 6e 5d 9c d8 73 66 89 a1 f6 7e |a...[4n]..sf...~| -00000320 01 bb 9a 5e 52 59 3f fc 3e 24 fc e7 49 10 83 9d |...^RY?.>$..I...| -00000330 fb 16 03 03 00 04 0e 00 00 00 |..........| +00000270 95 12 07 8f 2a 16 03 03 00 b6 0c 00 00 b2 03 00 |....*...........| +00000280 1d 20 6b 7f 5e 5e cd 37 8e 2a cf 07 bf 99 89 93 |. k.^^.7.*......| +00000290 05 be e6 3c 1d a8 67 07 b4 0d 28 22 be 3f 57 88 |...<..g...(".?W.| +000002a0 e4 41 04 03 00 8a 30 81 87 02 42 00 ce 0f 5f f7 |.A....0...B..._.| +000002b0 52 8c 44 e3 58 4c ed 4a 4f bf 2d 14 77 0f 3c a7 |R.D.XL.JO.-.w.<.| +000002c0 8a 7b fc 2d 0f 94 6e 51 01 51 e0 8c 58 b0 72 e4 |.{.-..nQ.Q..X.r.| +000002d0 57 cd ab ad fd a9 8c c2 e7 92 f3 0e e0 a0 22 64 |W............."d| +000002e0 a0 36 f9 e1 a3 f5 19 c8 8a b8 25 f6 0b 02 41 5d |.6........%...A]| +000002f0 d3 7c a0 42 5b f9 5d b8 f9 c2 a3 d4 8f 0e 4c c7 |.|.B[.].......L.| +00000300 d4 61 11 73 f0 35 7e b1 73 29 0f 97 52 75 8a 1f |.a.s.5~.s)..Ru..| +00000310 00 e9 6e 59 25 bb ca 72 bd 1e 4f 34 fc 55 ef 66 |..nY%..r..O4.U.f| +00000320 33 3d 5f fc e2 8d ac 09 7f 20 85 ca b3 a4 b3 ca |3=_...... ......| +00000330 16 03 03 00 04 0e 00 00 00 |.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 cf f9 90 26 e8 2c 00 99 ae 0e e6 |.... ...&.,.....| -00000040 a8 d9 66 6b 23 e7 c9 73 1c f7 e9 af e1 71 1d f3 |..fk#..s.....q..| -00000050 34 60 ee 16 9d |4`...| +00000030 16 03 03 00 20 1a fc 19 6c ef eb a5 d1 28 d9 aa |.... ...l....(..| +00000040 56 3f b7 12 a0 18 eb 76 16 be 6d 1e d9 3b 6f 14 |V?.....v..m..;o.| +00000050 51 68 9c 63 b3 |Qh.c.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 39 9f 39 3a 22 |.......... 9.9:"| -00000010 0b 27 cb 75 0d 43 98 11 06 dd 7e 73 17 e0 8a 19 |.'.u.C....~s....| -00000020 6d eb a8 33 c6 42 b4 e9 cb dd b1 |m..3.B.....| +00000000 14 03 03 00 01 01 16 03 03 00 20 38 c9 5f c3 6f |.......... 8._.o| +00000010 1b 84 54 77 40 98 70 cb f1 d1 5f 9e 11 16 24 c6 |..Tw@.p..._...$.| +00000020 c4 7e f0 44 32 2c ce 29 dd 8e 20 |.~.D2,.).. | >>> Flow 5 (client to server) -00000000 17 03 03 00 16 24 1f 08 49 ef 32 16 8d 76 c7 34 |.....$..I.2..v.4| -00000010 e0 08 cb d9 e7 72 aa 0f fb c4 94 15 03 03 00 12 |.....r..........| -00000020 38 0b 8c e0 0b 61 20 e8 a6 7c 77 69 fb 00 96 39 |8....a ..|wi...9| -00000030 b9 a7 |..| +00000000 17 03 03 00 16 86 12 a2 e2 ae df 03 ed e4 a4 74 |...............t| +00000010 d0 8b 8c 17 92 20 4d bd c2 29 ac 15 03 03 00 12 |..... M..)......| +00000020 e1 66 4e 21 16 24 34 9f 0f 95 63 80 d6 22 52 c4 |.fN!.$4...c.."R.| +00000030 67 ac |g.| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES index e2e935cc2e7..70b43803f15 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 8d 69 e3 6e 69 |....]...Y...i.ni| -00000010 45 96 8b 0d c8 7d 9c dc b6 75 24 ee 61 44 95 99 |E....}...u$.aD..| -00000020 cb a8 da df 35 ac c3 36 02 3f b9 20 2d c2 47 c9 |....5..6.?. -.G.| -00000030 f0 47 80 9a c6 bd e4 1b ca d6 62 17 59 ec c9 83 |.G........b.Y...| -00000040 d5 ed 3f 2c 13 b0 30 0a 5e 1f 0e db c0 13 00 00 |..?,..0.^.......| +00000000 16 03 03 00 5d 02 00 00 59 03 03 c7 61 5d 9b a7 |....]...Y...a]..| +00000010 9f 27 4f de 56 2b 83 b8 dc 21 7d 27 e5 23 c0 b4 |.'O.V+...!}'.#..| +00000020 a7 b1 61 3c 7c b7 af 1a b0 c6 ed 20 82 8c 08 27 |..a<|...... ...'| +00000030 79 99 c6 a7 dd 7e 33 bb 6c d0 4b 4a 02 e7 2e 87 |y....~3.l.KJ....| +00000040 69 24 05 ac 32 6f 40 4f dc 2e 11 3f c0 13 00 00 |i$..2o@O...?....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,38 +62,38 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 0f 4e 12 |............ .N.| -000002d0 ab ce 7e 62 68 64 e0 1d 7e 33 a2 ee 5d e7 2d d5 |..~bhd..~3..].-.| -000002e0 d2 dc d0 ce b2 7e 9b be 33 8d 9c 56 7a 08 04 00 |.....~..3..Vz...| -000002f0 80 44 b8 9b 87 5f 84 f6 8a 99 af e9 f7 f8 88 fd |.D..._..........| -00000300 f7 12 02 48 a1 fa 66 9c 89 a2 dc bf fd 41 08 fa |...H..f......A..| -00000310 6f e4 44 09 8e c1 45 bb 2a e9 e3 45 19 a3 81 50 |o.D...E.*..E...P| -00000320 99 46 5f 86 5b 6b c0 29 d1 e5 21 4b 56 af f4 d0 |.F_.[k.)..!KV...| -00000330 63 c4 75 ac f6 75 61 ca fe 1a b9 70 4d 14 50 b1 |c.u..ua....pM.P.| -00000340 12 7f 29 2d c5 d7 78 da 06 3e 4c 47 75 8a a6 01 |..)-..x..>LGu...| -00000350 37 17 1c e8 ef 94 85 d0 e2 ee d5 25 ae 8d f8 e6 |7..........%....| -00000360 90 10 12 37 b4 0f f5 c7 a2 85 1a 83 8a 38 e6 32 |...7.........8.2| -00000370 98 16 03 03 00 04 0e 00 00 00 |..........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 5c ce 07 |............ \..| +000002d0 a8 0b 8f ff 08 19 e7 d7 38 62 98 bf c1 f7 92 27 |........8b.....'| +000002e0 cb 7b 5e 50 36 51 83 61 8d b4 d6 29 1c 08 04 00 |.{^P6Q.a...)....| +000002f0 80 98 88 66 48 81 8b 9d 9b e0 6e 6e c4 c4 99 fb |...fH.....nn....| +00000300 63 46 fd 8c 7e e1 d0 dd 01 e6 bb 23 97 b8 21 2e |cF..~......#..!.| +00000310 53 06 e0 5d 58 c8 79 c3 01 a5 01 e2 81 7b c7 a9 |S..]X.y......{..| +00000320 04 15 98 9b 53 98 42 0b 3d 4e 97 93 b9 88 80 2c |....S.B.=N.....,| +00000330 78 fd 9b 99 12 7f a8 de a0 c0 c4 1d 15 59 d4 d8 |x............Y..| +00000340 ef 0d bd 0b 46 c3 6e e6 4b 04 69 91 c0 db 74 ca |....F.n.K.i...t.| +00000350 99 2e 6f 47 8b 9b 22 3f b3 4a e3 10 47 2d dd 47 |..oG.."?.J..G-.G| +00000360 d5 e1 9b 66 8f d9 b2 fb b7 52 ae 6a 14 74 32 2d |...f.....R.j.t2-| +00000370 6e 16 03 03 00 04 0e 00 00 00 |n.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 6c 72 1c 47 f9 89 fa 2b 0e cf 69 |.....lr.G...+..i| -00000050 bf 95 e4 ea b8 74 e7 99 d4 c4 53 f5 97 f5 08 f9 |.....t....S.....| -00000060 ef 03 e7 76 b8 2c 31 f6 9b 2c cd 27 c8 42 6a a8 |...v.,1..,.'.Bj.| -00000070 c0 e0 b9 5e cd |...^.| +00000040 00 00 00 00 00 99 c9 2d 35 8b 96 18 36 f4 db a4 |.......-5...6...| +00000050 9a 56 67 6a 6b 9d ee b1 cb 95 54 43 93 7c 0e ff |.Vgjk.....TC.|..| +00000060 c0 54 84 83 14 bf d5 95 85 a1 b5 c5 2c fe c3 29 |.T..........,..)| +00000070 81 7b 1e 16 2e |.{...| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 89 35 48 2e 99 |..........@.5H..| -00000010 7c 13 76 5e 7f 07 a6 44 d9 95 1c 9f 25 59 3d f5 ||.v^...D....%Y=.| -00000020 df d6 5e cb 85 3e 0c f7 48 69 95 77 29 95 88 1c |..^..>..Hi.w)...| -00000030 1e 76 8a c3 ea 69 07 75 46 68 09 50 fa 30 0a 57 |.v...i.uFh.P.0.W| -00000040 84 e3 c7 d9 34 c4 40 32 7b f4 95 |....4.@2{..| +00000000 14 03 03 00 01 01 16 03 03 00 40 8b 6e b0 cb bf |..........@.n...| +00000010 35 8d c3 7e 48 27 92 77 20 8a 38 c6 81 94 17 d4 |5..~H'.w .8.....| +00000020 b8 18 4e 23 e7 8b 0a 89 7b d1 72 58 aa b9 9b bb |..N#....{.rX....| +00000030 c9 40 c7 c4 8e 74 77 f3 3e 90 9c b0 19 04 6c ea |.@...tw.>.....l.| +00000040 87 85 f1 fd d9 fd 2d 57 57 f1 c9 |......-WW..| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 24 6d d9 23 68 ad 8d 64 2e 3a d5 |.....$m.#h..d.:.| -00000020 ed eb 4c e9 cb 9d 13 49 4c 44 b9 00 af af 2c e7 |..L....ILD....,.| -00000030 22 c0 bb 31 4e 15 03 03 00 30 00 00 00 00 00 00 |"..1N....0......| -00000040 00 00 00 00 00 00 00 00 00 00 c8 60 b8 c1 66 9b |...........`..f.| -00000050 52 44 3c 26 7f ff 96 a6 21 c7 eb 33 71 f8 40 23 |RD<&....!..3q.@#| -00000060 7c 5b ef b2 e1 b4 3f 84 82 48 ||[....?..H| +00000010 00 00 00 00 00 b9 8c 86 6d 84 db d0 60 f7 11 22 |........m...`.."| +00000020 97 52 b3 fe bb 1c 0c bd 26 9c a1 84 51 3d a2 2b |.R......&...Q=.+| +00000030 c0 79 e5 a5 96 15 03 03 00 30 00 00 00 00 00 00 |.y.......0......| +00000040 00 00 00 00 00 00 00 00 00 00 7a 42 27 d5 ae 30 |..........zB'..0| +00000050 81 b5 94 05 55 c9 93 e0 11 98 6d f8 aa 18 92 f4 |....U.....m.....| +00000060 32 8f d1 aa a6 86 cd df 11 c2 |2.........| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 index f8f04ac13b5..9081031e737 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 8f cc 68 50 60 |....]...Y....hP`| -00000010 11 c8 c3 ce e7 e9 e1 3c fb 29 d7 4f df 44 16 65 |.......<.).O.D.e| -00000020 1d 3b 25 5b 32 59 f1 8e be d8 49 20 c2 89 a7 d5 |.;%[2Y....I ....| -00000030 cb 2c a2 05 19 6b 65 64 9b 71 2b d3 d2 19 cb 66 |.,...ked.q+....f| -00000040 61 c1 6f 19 b4 7a 15 41 76 14 85 fc c0 27 00 00 |a.o..z.Av....'..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 7b 18 cc 97 f2 |....]...Y..{....| +00000010 59 62 62 18 bc ee e1 09 0c 7b 8c 3e f0 36 3d 8b |Ybb......{.>.6=.| +00000020 96 54 26 93 c8 ac bb 7c 19 63 6a 20 96 8e 51 d2 |.T&....|.cj ..Q.| +00000030 18 6d 8a 72 6b 5d d2 5e 2b 53 4e a5 43 cf 75 4f |.m.rk].^+SN.C.uO| +00000040 e6 9c 3a 30 f5 23 3f bf 66 bc fe a2 c0 27 00 00 |..:0.#?.f....'..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,42 +62,42 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 88 db 33 |............ ..3| -000002d0 96 fb ae 63 de f8 2b 4b 94 fa da c2 8e 75 fa 63 |...c..+K.....u.c| -000002e0 0a 54 2b 68 01 76 2a 76 4f e7 91 e9 2a 08 04 00 |.T+h.v*vO...*...| -000002f0 80 d9 47 dd dd b9 94 b8 1c 1b dc 1f 79 bd f1 26 |..G.........y..&| -00000300 66 19 52 0b 0a 2e ea 0d 69 bf 93 a0 29 0f 6a 30 |f.R.....i...).j0| -00000310 2c 1b 44 25 13 e3 b7 03 db b3 fc 37 9c 3f bb e7 |,.D%.......7.?..| -00000320 c7 4d 65 8f af bb 39 fa 6e 77 09 bb 08 09 7e d1 |.Me...9.nw....~.| -00000330 0f ad 57 78 a6 cb a8 3f 2e 70 fc 38 75 2f a0 23 |..Wx...?.p.8u/.#| -00000340 0b 0c 6c 28 0a 71 51 dc 10 8f 85 fd 97 0f c4 84 |..l(.qQ.........| -00000350 80 cf 70 0a a9 56 9a af 2f ab 12 c7 8b d1 82 1c |..p..V../.......| -00000360 f0 6c 08 00 73 18 dd 6e 5a 66 ed a5 f7 7a 3d 73 |.l..s..nZf...z=s| -00000370 88 16 03 03 00 04 0e 00 00 00 |..........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 e4 05 36 |............ ..6| +000002d0 05 47 cf b0 62 f8 f6 d6 e0 ce a5 f9 45 f6 28 f9 |.G..b.......E.(.| +000002e0 d2 58 47 6c 0a 58 9d 85 74 52 d3 0d 17 08 04 00 |.XGl.X..tR......| +000002f0 80 d0 8b 12 95 dd 2a 7f b2 55 33 e0 13 28 41 47 |......*..U3..(AG| +00000300 06 38 fe fb 11 b3 3f 66 c4 62 db 1c f9 29 9e ea |.8....?f.b...)..| +00000310 2f e4 62 22 4f 99 36 05 fb 89 8f d5 29 bf a6 e0 |/.b"O.6.....)...| +00000320 fc 12 88 d8 60 9a 4d 82 eb 64 ba 99 1c 1c 82 ff |....`.M..d......| +00000330 df 57 a9 b9 14 d5 a7 ad 57 45 1d e0 91 db 61 90 |.W......WE....a.| +00000340 ca 15 9b 0c 49 f8 a9 40 5f 34 6b d2 fe 00 48 e5 |....I..@_4k...H.| +00000350 ea 1e 3b ae 1f 81 a9 d7 91 ff 46 e9 af 48 04 b3 |..;.......F..H..| +00000360 83 0c 95 91 ea 5f 1f 5b 48 98 2a 9c f6 80 2a db |....._.[H.*...*.| +00000370 d2 16 03 03 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| -00000040 00 00 00 00 00 93 01 19 de 19 e6 58 a9 b2 bb e6 |...........X....| -00000050 83 08 03 78 72 d8 25 fc 31 70 55 fa cd ec e4 0a |...xr.%.1pU.....| -00000060 a2 7b 00 5c fe 7f 08 26 a5 ca 9f d6 28 95 69 f5 |.{.\...&....(.i.| -00000070 b9 17 23 34 83 fe 36 24 60 17 4c 90 18 30 f9 44 |..#4..6$`.L..0.D| -00000080 af 74 ea 65 4b |.t.eK| +00000040 00 00 00 00 00 c0 4e 63 30 1d 23 c8 dc ef 03 e9 |......Nc0.#.....| +00000050 29 7c 61 b8 7a a4 52 c3 09 f4 aa 97 30 3c 5a 7c |)|a.z.R.....0>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 b6 cf 83 c7 0d |..........P.....| -00000010 dc 8f 9a 96 0d 0b 4f 58 ed c9 46 fa 95 0b f1 ab |......OX..F.....| -00000020 9a 50 2a cc af 26 73 03 0b 93 e7 4e 96 a0 e2 44 |.P*..&s....N...D| -00000030 01 99 9e 06 a3 81 3f 0b e4 7c 03 53 e4 65 36 69 |......?..|.S.e6i| -00000040 65 96 79 a2 4e 79 e8 fc b1 6a 50 3e dd 22 1f e3 |e.y.Ny...jP>."..| -00000050 fe e3 77 9f 8c 05 f8 cc 08 4b 6b |..w......Kk| +00000000 14 03 03 00 01 01 16 03 03 00 50 bd 21 3f c1 94 |..........P.!?..| +00000010 2f 3e 00 3c 43 00 17 39 90 74 b2 4f 40 5d 0c 2b |/>.>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 f8 39 8e 57 60 18 1c ef 19 c8 da |......9.W`......| -00000020 f4 3b dc 42 85 44 e3 59 28 ea 29 11 60 ba 2b 2b |.;.B.D.Y(.).`.++| -00000030 dc 6a 5d 3a ed ce f2 10 34 17 6e 10 67 00 f0 43 |.j]:....4.n.g..C| -00000040 3e 0f e1 a1 c8 15 03 03 00 40 00 00 00 00 00 00 |>........@......| -00000050 00 00 00 00 00 00 00 00 00 00 13 0d fa 71 e4 df |.............q..| -00000060 76 f3 c9 01 d5 60 b4 34 d4 6f 68 f5 cd af d6 0b |v....`.4.oh.....| -00000070 e6 af ab ec 64 75 38 d6 17 d4 27 81 96 e5 71 74 |....du8...'...qt| -00000080 d5 cd 39 30 35 4a ef 92 56 6e |..905J..Vn| +00000010 00 00 00 00 00 ad 41 d8 27 7d f4 06 b7 6c 89 f4 |......A.'}...l..| +00000020 e3 c5 de 6d 06 80 0c 2e f8 42 5a 2c da f1 e2 b6 |...m.....BZ,....| +00000030 e6 e8 6f 5c ee e0 aa 4b d6 8a 7a 04 6a 5e 8c 99 |..o\...K..z.j^..| +00000040 1b 36 be f9 d0 15 03 03 00 40 00 00 00 00 00 00 |.6.......@......| +00000050 00 00 00 00 00 00 00 00 00 00 f1 cf 76 91 15 bd |............v...| +00000060 33 f3 96 25 c7 d9 77 30 a6 84 1a 06 c1 96 96 27 |3..%..w0.......'| +00000070 70 ff d2 ce 82 1e 39 8f 19 75 c7 f2 0f cb de bc |p.....9..u......| +00000080 9a ef 4c 93 e3 3c 0c 2f 97 ad |..L..<./..| diff --git a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 index 2ea5debf2d6..30ea8ec568a 100644 --- a/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 +++ b/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 @@ -1,24 +1,26 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 d4 01 00 00 d0 03 03 00 00 00 00 00 |................| +00000000 16 03 01 00 ee 01 00 00 ea 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a8 |................| -00000050 13 03 13 01 13 02 01 00 00 7f 00 0b 00 02 01 00 |................| +00000050 13 03 13 01 13 02 01 00 00 99 00 0b 00 02 01 00 |................| 00000060 ff 01 00 01 00 00 17 00 00 00 12 00 00 00 05 00 |................| 00000070 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 |................| -00000080 00 18 00 19 00 0d 00 1a 00 18 08 04 04 03 08 07 |................| -00000090 08 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01 |................| -000000a0 02 03 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| -000000b0 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 |3.&.$... /.}.G.b| -000000c0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -000000d0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| +00000080 00 18 00 19 00 0d 00 16 00 14 08 04 04 03 08 07 |................| +00000090 08 05 08 06 04 01 05 01 06 01 05 03 06 03 00 32 |...............2| +000000a0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000b0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| +000000c0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| +000000d0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| +000000e0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| +000000f0 cb 3b 74 |.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 01 ce 8f f1 84 |....]...Y.......| -00000010 65 dc 47 4e 43 f2 cd 85 6c 98 40 a7 5c 7f ed 53 |e.GNC...l.@.\..S| -00000020 78 63 03 dd 50 3e a4 27 20 21 bf 20 d9 93 9d f6 |xc..P>.' !. ....| -00000030 1f e8 0e 72 fc 64 e0 dd 8e ef b3 ea ff 5b ad 60 |...r.d.......[.`| -00000040 a5 f0 68 ff 7e 35 46 a4 28 71 31 fd cc a8 00 00 |..h.~5F.(q1.....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 1b 61 37 54 ad |....]...Y...a7T.| +00000010 7e 92 6a 93 df 5e f8 16 be e7 06 12 3f e7 23 84 |~.j..^......?.#.| +00000020 be 2a 30 78 98 cf 60 8a 8a 2d 26 20 44 fb 40 31 |.*0x..`..-& D.@1| +00000030 88 38 6e fc ce 1d af 07 e3 c0 49 05 ff bc 92 ae |.8n.......I.....| +00000040 58 79 51 ec a7 24 82 75 9a 16 45 fa cc a8 00 00 |XyQ..$.u..E.....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -58,31 +60,31 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 ea 03 c7 |............ ...| -000002d0 b0 eb 76 ba 86 25 18 e5 0d b3 70 2a 41 72 4d 88 |..v..%....p*ArM.| -000002e0 55 6d 91 2b 65 fe e0 64 12 69 42 eb 27 08 04 00 |Um.+e..d.iB.'...| -000002f0 80 0f 00 0a b0 35 db 39 fa ba a1 27 44 e0 9b d4 |.....5.9...'D...| -00000300 b8 aa b3 4f 93 46 ed 09 f8 3e 1b c8 47 6e 52 8a |...O.F...>..GnR.| -00000310 8f fd b1 67 f6 05 87 68 de 7b 25 1b 40 df 1e f2 |...g...h.{%.@...| -00000320 04 2b 4f 39 3d 6f a8 f7 25 37 26 34 87 84 06 c4 |.+O9=o..%7&4....| -00000330 0e 31 bc 46 8a d2 99 14 6d 5d 14 32 a2 32 fc 10 |.1.F....m].2.2..| -00000340 5e fb d9 f8 06 d4 05 17 5d 59 f4 38 c5 13 1c 91 |^.......]Y.8....| -00000350 5a 5f cb dd 3e 27 78 10 2c 0c 9b 7f 1a ec 4c da |Z_..>'x.,.....L.| -00000360 fb d7 52 eb 76 83 75 87 d2 a3 7f e9 25 a5 8a 22 |..R.v.u.....%.."| -00000370 dd 16 03 03 00 04 0e 00 00 00 |..........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 8b cc 79 |............ ..y| +000002d0 1e 8e 20 61 5d 00 97 27 cb 24 5c 7c 5f 3f df db |.. a]..'.$\|_?..| +000002e0 2d ba 3b f4 a1 1d 3e 3c 08 da 98 22 68 08 04 00 |-.;...><..."h...| +000002f0 80 10 fc 5b 90 af a6 8e d4 1b 5e 63 13 55 88 55 |...[......^c.U.U| +00000300 f3 bb ad 7a 5b 14 95 55 6b 2f 01 eb 22 88 fb 21 |...z[..Uk/.."..!| +00000310 40 88 d1 7f 52 b2 a2 ff 51 f9 05 8c c8 28 70 77 |@...R...Q....(pw| +00000320 3c 7a b0 48 28 f0 34 19 cc 8e c8 c9 43 93 aa fa |..a...4..r}..| +00000360 98 f2 bb c0 ae 5f b8 8e 00 6a 47 9c 8d cf 91 eb |....._...jG.....| +00000370 e7 16 03 03 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 28 48 18 85 9d 35 c7 5a 46 2c a7 |.... (H...5.ZF,.| -00000040 5b 8b c0 71 73 66 d0 a7 53 a0 e3 ed c8 57 f3 70 |[..qsf..S....W.p| -00000050 9a 01 58 61 84 |..Xa.| +00000030 16 03 03 00 20 af 23 75 51 f1 3c 68 f8 87 2e 2b |.... .#uQ.>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 b9 72 f6 07 40 |.......... .r..@| -00000010 0b 2f 67 8a 97 fa 17 24 81 e5 6f 5b 09 90 72 8d |./g....$..o[..r.| -00000020 48 59 14 00 34 e8 3c 82 b8 2f 87 |HY..4.<../.| +00000000 14 03 03 00 01 01 16 03 03 00 20 c0 52 cb d5 de |.......... .R...| +00000010 b1 43 8a 0b 75 a6 a4 d4 8f af 85 63 71 1d 3b 4f |.C..u......cq.;O| +00000020 7a ad 9b 77 85 1a 1d 7e 4b 42 13 |z..w...~KB.| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 f6 cf b1 93 64 54 56 f3 35 3d 8f |.........dTV.5=.| -00000010 31 5e 66 62 56 aa e9 81 47 4c 8b 15 03 03 00 12 |1^fbV...GL......| -00000020 de 0b 32 2b 58 2c b5 4e 80 2a 66 e7 a0 a9 28 d9 |..2+X,.N.*f...(.| -00000030 db 11 |..| +00000000 17 03 03 00 16 30 b8 0e dd 42 64 a4 17 ee f5 70 |.....0...Bd....p| +00000010 1e 00 e8 da a7 f6 8e 73 c7 70 32 15 03 03 00 12 |.......s.p2.....| +00000020 57 be 7b cf bb 7b fe cb 7e b2 bb 38 9f 31 65 07 |W.{..{..~..8.1e.| +00000030 ba 61 |.a| diff --git a/crypto/tls/testdata/Client-TLSv12-Ed25519 b/crypto/tls/testdata/Client-TLSv12-Ed25519 index d43ee07eeab..40b2f35137d 100644 --- a/crypto/tls/testdata/Client-TLSv12-Ed25519 +++ b/crypto/tls/testdata/Client-TLSv12-Ed25519 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 93 8a a3 77 84 |....]...Y.....w.| -00000010 fd 41 3d a5 ad b5 eb 91 63 a6 b5 3a 5f 21 08 df |.A=.....c..:_!..| -00000020 72 07 be 1f df d7 4e 6f f3 f8 cb 20 ae d3 e5 fe |r.....No... ....| -00000030 53 a3 c7 84 6c 3e c6 1d d5 65 5d a6 a5 7d f7 5c |S...l>...e]..}.\| -00000040 34 65 a7 df 1e 28 3f 7d 20 08 81 2c cc a9 00 00 |4e...(?} ..,....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 cc 3c fc d0 c6 |....]...Y...<...| +00000010 b8 3e 6b cb 59 8d 68 04 0b 94 10 28 ad 71 06 14 |.>k.Y.h....(.q..| +00000020 08 6c 10 12 aa 8d e4 f9 aa 7d 9b 20 a0 b8 96 40 |.l.......}. ...@| +00000030 1a ce 65 ae a6 a2 4d 4d 92 41 8e 2c 8d 94 d1 02 |..e...MM.A.,....| +00000040 c1 cb bd 6d 8b ee 36 ae c5 ec 6a 40 cc a9 00 00 |...m..6...j@....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 |......<...8..5..| 00000070 32 30 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 0f |20...0..........| @@ -44,26 +45,26 @@ 00000180 fc ab 7d 4d d4 e0 93 13 d0 a9 42 e0 b6 6b fe 5d |..}M......B..k.]| 00000190 67 48 d7 9f 50 bc 6c cd 4b 03 83 7c f2 08 58 cd |gH..P.l.K..|..X.| 000001a0 ac cf 0c 16 03 03 00 6c 0c 00 00 68 03 00 1d 20 |.......l...h... | -000001b0 e9 e7 75 b4 4c 42 14 7a e0 50 0a 95 f1 d7 35 aa |..u.LB.z.P....5.| -000001c0 39 05 9e 59 73 5e cd d2 ec 56 18 f0 ee 1f 81 3c |9..Ys^...V.....<| -000001d0 08 07 00 40 44 e9 19 b6 00 49 f7 c8 06 62 cb c1 |...@D....I...b..| -000001e0 b5 7c b6 cd 32 47 c9 05 82 3b f0 af d1 cd 75 8b |.|..2G...;....u.| -000001f0 82 8b 47 dd 85 13 78 69 5d 40 7e 9b 91 24 2e ce |..G...xi]@~..$..| -00000200 3e be e0 12 1e ec 56 0b ff 25 21 92 6f 24 12 10 |>.....V..%!.o$..| -00000210 30 33 cf 04 16 03 03 00 04 0e 00 00 00 |03...........| +000001b0 fd f1 12 74 21 62 15 da 36 af d5 6c f3 0a cd 1e |...t!b..6..l....| +000001c0 09 37 aa 55 32 1a 27 a7 5b 37 34 32 35 36 f5 14 |.7.U2.'.[74256..| +000001d0 08 07 00 40 3d 7c 51 33 98 02 91 19 da 47 1a 1a |...@=|Q3.....G..| +000001e0 fe 03 4e 1b e8 5c 5e a7 12 9c e6 8a c2 74 18 dd |..N..\^......t..| +000001f0 18 9a 9d d6 60 f3 c8 63 00 33 d8 81 3e 2e 40 0f |....`..c.3..>.@.| +00000200 c5 98 fc a8 1c 6b 0c 19 70 f5 16 a5 25 ce 7b b8 |.....k..p...%.{.| +00000210 f2 f5 87 04 16 03 03 00 04 0e 00 00 00 |.............| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 69 ac be cf f1 3d 8a 4e f3 3a 54 |.... i....=.N.:T| -00000040 05 d8 20 3a f0 67 40 3f 5b 94 cf a4 3e ec 8e 4e |.. :.g@?[...>..N| -00000050 75 c9 92 2c af |u..,.| +00000030 16 03 03 00 20 91 a7 c4 90 65 85 ce 63 66 fa 8b |.... ....e..cf..| +00000040 5c 22 e1 1d fb 14 c2 6c 86 7c 52 7c d1 96 3b 41 |\".....l.|R|..;A| +00000050 20 0d bf 09 e8 | ....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 70 c5 f8 c7 7c |.......... p...|| -00000010 4a 34 6f b0 eb 1b 13 c7 e0 21 32 cf ce 89 aa 53 |J4o......!2....S| -00000020 5f 67 b8 a7 3e 10 bb a3 5f fa 2f |_g..>..._./| +00000000 14 03 03 00 01 01 16 03 03 00 20 d0 3e 15 0e 08 |.......... .>...| +00000010 5b fd a8 b7 5f 01 7f ca 6d af 78 6e 33 7a 93 42 |[..._...m.xn3z.B| +00000020 aa 6e e4 f4 a1 bb 9a 2d bb 17 6f |.n.....-..o| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 54 ae 8d 1c 04 40 47 8a 7e ac c3 |.....T....@G.~..| -00000010 21 a2 8a f0 5d 3d 12 9d b0 b5 8d 15 03 03 00 12 |!...]=..........| -00000020 71 3b 30 89 d4 c3 ef 34 66 92 29 1b e1 af d4 d2 |q;0....4f.).....| -00000030 7e cd |~.| +00000000 17 03 03 00 16 7b f9 2f ce ac bc 43 3c 6b 10 3b |.....{./...C>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 18 47 80 ab 8d |....]...Y...G...| -00000010 42 c7 73 06 75 ef 28 ff 87 46 49 af 3a 3b cb bb |B.s.u.(..FI.:;..| -00000020 ff 6e e3 60 11 40 2c b8 40 87 5c 20 86 3d de c2 |.n.`.@,.@.\ .=..| -00000030 18 41 ff 1a dc 00 77 4e 17 0b 36 f3 69 92 d7 04 |.A....wN..6.i...| -00000040 c4 c6 39 ad ed f7 06 23 8c 52 50 da cc a8 00 00 |..9....#.RP.....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 ad 2d c6 4e 13 |....]...Y...-.N.| +00000010 72 ea 19 e0 65 33 ec cb aa 5c 70 bd f5 70 e0 b4 |r...e3...\p..p..| +00000020 ca 7e 64 da 5e 5f cb a6 69 d4 8c 20 79 45 e2 0a |.~d.^_..i.. yE..| +00000030 c7 b2 be 37 28 b5 c6 35 f9 0c c9 34 39 4d 38 3b |...7(..5...49M8;| +00000040 c0 47 31 44 e2 47 f7 6f 70 0f 8b 2d cc a8 00 00 |.G1D.G.op..-....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,31 +62,31 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 c5 28 44 |............ .(D| -000002d0 4a 31 d9 b6 53 90 8e 41 3c 67 2c 6f 9d b0 a6 d3 |J1..S..A>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 9f 16 49 2a d8 cc 0a 45 92 8d c2 |.... ..I*...E...| -00000040 25 3c b1 5c a8 f2 c4 9b c4 2a 66 fe 7f 87 df 35 |%<.\.....*f....5| -00000050 77 a4 b0 05 f5 |w....| +00000030 16 03 03 00 20 e1 88 c9 ef 40 26 52 ca d2 d9 31 |.... ....@&R...1| +00000040 9c 51 a6 fa b3 40 6b 62 7e ad 00 ea da 8f 54 bf |.Q...@kb~.....T.| +00000050 f5 89 4b c9 a9 |..K..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 37 55 d5 05 71 |.......... 7U..q| -00000010 a0 00 44 56 32 c3 c8 e6 68 5e de d4 e7 65 56 d3 |..DV2...h^...eV.| -00000020 2d 93 07 e6 72 17 e9 49 74 4d c0 |-...r..ItM.| +00000000 14 03 03 00 01 01 16 03 03 00 20 6f e3 54 91 aa |.......... o.T..| +00000010 00 b4 8e f3 b2 51 1e 76 48 91 49 b9 ba dc 5f e4 |.....Q.vH.I..._.| +00000020 9f 0e 49 b5 54 f5 e3 9d 25 75 38 |..I.T...%u8| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 27 a6 31 16 5c 7e bd 05 0a 2c 05 |.....'.1.\~...,.| -00000010 ba 37 06 00 d7 8d 66 a7 8e 16 7b 15 03 03 00 12 |.7....f...{.....| -00000020 70 38 bc 7e 6b 83 83 e1 61 3b bb a5 d9 dc f7 e7 |p8.~k...a;......| -00000030 5e 12 |^.| +00000000 17 03 03 00 16 7b 2a af 79 d3 1c 0d cf 0f 83 04 |.....{*.y.......| +00000010 9e 96 63 69 0c ec f7 98 02 33 12 15 03 03 00 12 |..ci.....3......| +00000020 58 d3 1a 60 74 2c 92 91 61 2c 13 23 6d e9 5f de |X..`t,..a,.#m._.| +00000030 65 42 |eB| diff --git a/crypto/tls/testdata/Client-TLSv12-P256-ECDHE b/crypto/tls/testdata/Client-TLSv12-P256-ECDHE index 7a0a53c03a0..0cac7e7545c 100644 --- a/crypto/tls/testdata/Client-TLSv12-P256-ECDHE +++ b/crypto/tls/testdata/Client-TLSv12-P256-ECDHE @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 01 19 01 00 01 15 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 33 01 00 01 2f 03 03 00 00 00 00 00 |....3.../.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,22 +7,24 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 9a 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 b4 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| -000000a0 00 0a 00 04 00 02 00 17 00 0d 00 1a 00 18 08 04 |................| +000000a0 00 0a 00 04 00 02 00 17 00 0d 00 16 00 14 08 04 |................| 000000b0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| -000000c0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| -000000d0 02 03 01 00 33 00 47 00 45 00 17 00 41 04 1e 18 |....3.G.E...A...| -000000e0 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f |7...Q.5uq..T[...| -000000f0 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b |.g..$ >.V...(^.+| -00000100 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 |-O....lK[.V.2B.X| -00000110 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |..I..h.A.Vk.Z.| +000000c0 06 03 00 32 00 1a 00 18 08 04 04 03 08 07 08 05 |...2............| +000000d0 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 |................| +000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| +000000f0 47 00 45 00 17 00 41 04 1e 18 37 ef 0d 19 51 88 |G.E...A...7...Q.| +00000100 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ | +00000110 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....| +00000120 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h| +00000130 1a 41 03 56 6b dc 5a 89 |.A.Vk.Z.| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 1c ad ae e9 64 |....]...Y......d| -00000010 35 80 c6 04 f5 69 05 bb 5c 38 78 d3 99 2f ad e6 |5....i..\8x../..| -00000020 56 20 d4 79 89 1a 51 54 14 ac 6d 20 06 6d 1a bd |V .y..QT..m .m..| -00000030 04 cf 4f 42 3d aa 31 3b fb dc c1 85 42 c3 6d 12 |..OB=.1;....B.m.| -00000040 27 98 be 4b 88 93 45 0e 78 ba d8 13 c0 2f 00 00 |'..K..E.x..../..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 d9 70 61 62 c5 |....]...Y...pab.| +00000010 f4 b4 22 c6 ea f6 e9 8c fc 29 e8 8c 24 2d 4b c4 |.."......)..$-K.| +00000020 04 57 01 ae e5 41 7e 7f 6f ec c3 20 86 6b 38 a9 |.W...A~.o.. .k8.| +00000030 ea cd 51 3b 0f 05 5c a3 98 0c 4d ba 46 d6 99 f3 |..Q;..\...M.F...| +00000040 67 da f2 62 56 29 f7 e6 8c 14 8a 7a c0 2f 00 00 |g..bV).....z./..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -62,37 +64,37 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 3a 1c |............A.:.| -000002d0 84 6b e6 cb 7d 3f bd ea d7 7a c3 63 43 77 f7 14 |.k..}?...z.cCw..| -000002e0 a7 98 52 86 49 4d 05 b2 70 e2 d3 44 c9 05 eb 83 |..R.IM..p..D....| -000002f0 b4 11 c5 3e 9d 3b 3b cd de d0 df 78 83 0f 0c d8 |...>.;;....x....| -00000300 76 e7 19 9d 1f 5a 3d 2a 54 19 16 a0 c2 55 08 04 |v....Z=*T....U..| -00000310 00 80 09 ee 97 8a d1 82 fc 4a fc f2 89 d2 a3 c7 |.........J......| -00000320 8c 25 74 98 cf b5 67 c6 fd f6 0d 3b 62 ba 31 ca |.%t...g....;b.1.| -00000330 d1 67 aa c3 32 89 ee 83 22 d2 b7 3c f8 98 af 16 |.g..2..."..<....| -00000340 dd 05 06 2c c4 57 dd fc 22 3a 2e 80 f9 84 6a ee |...,.W..":....j.| -00000350 f2 a1 21 d1 0f db 17 50 a1 35 94 b3 0a b7 62 ca |..!....P.5....b.| -00000360 2c b3 0b 68 0c 58 d7 24 83 82 d8 34 64 3f a4 61 |,..h.X.$...4d?.a| -00000370 0e b1 ca 93 67 b3 51 11 dc 49 f2 df 26 89 8b ea |....g.Q..I..&...| -00000380 22 09 1a be 62 27 61 c8 93 4b dd 95 31 6a ba e2 |"...b'a..K..1j..| -00000390 c3 2b 16 03 03 00 04 0e 00 00 00 |.+.........| +000002c0 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 a0 b7 |............A...| +000002d0 0f 94 44 46 c4 72 5a 3c b8 5c cd f1 9e b0 49 17 |..DF.rZ<.\....I.| +000002e0 ea a0 ca 1d 17 d8 85 5f 0a e3 4a 85 5d f4 bb 52 |......._..J.]..R| +000002f0 23 79 24 a9 50 81 9f 8a 5e e4 2f 5d cc 7d e2 10 |#y$.P...^./].}..| +00000300 db 42 f0 26 98 61 b7 f5 39 16 46 d6 04 f7 08 04 |.B.&.a..9.F.....| +00000310 00 80 05 70 60 b3 39 e0 61 6e 72 b3 13 2c 8c 2d |...p`.9.anr..,.-| +00000320 e1 d9 37 8e cd 13 64 2f 4b 65 4f 7c a0 2a 7e 91 |..7...d/KeO|.*~.| +00000330 e1 fd 7d 3b e3 35 dd 5a c8 ab 56 13 c3 c6 07 90 |..};.5.Z..V.....| +00000340 fb d3 cf 22 dd 78 4c 33 c7 d3 6e 64 7e 65 ba 02 |...".xL3..nd~e..| +00000350 ca 04 50 77 08 65 d5 80 c9 4f c3 b3 5b 97 b2 80 |..Pw.e...O..[...| +00000360 3d 48 37 20 ab 28 15 0c f2 86 dd b6 19 66 46 e3 |=H7 .(.......fF.| +00000370 23 69 e2 5d fb 70 65 fb c6 ae fc a4 02 42 9f fe |#i.].pe......B..| +00000380 b4 5c f0 4b 23 92 2a 4f a4 1a f4 86 3b 5c 25 9d |.\.K#.*O....;\%.| +00000390 86 e2 16 03 03 00 04 0e 00 00 00 |...........| >>> Flow 3 (client to server) 00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| 00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| 00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| 00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| 00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| -00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 fa c4 |.....(..........| -00000060 4e 47 d1 de 6d 60 fc af 59 43 7f 2f 4c b3 6e aa |NG..m`..YC./L.n.| -00000070 6f c3 bc 8a 40 5e e9 9c d9 b0 87 c5 92 41 |o...@^.......A| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 3f 54 |.....(........?T| +00000060 35 c8 33 70 66 0f 9d 3d 57 d7 a8 7f 57 45 63 a4 |5.3pf..=W...WEc.| +00000070 67 a2 83 c4 17 5b 22 8f 1c 89 78 1c 43 8d |g....["...x.C.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 eb 92 83 02 be |..........(.....| -00000010 89 55 4e 77 b2 45 1d 15 fd e0 6a 36 ab 0c 7b 4a |.UNw.E....j6..{J| -00000020 5d 50 e2 5a f3 c6 10 e2 ac ac a4 d3 4c 2e d8 31 |]P.Z........L..1| -00000030 84 31 17 |.1.| +00000000 14 03 03 00 01 01 16 03 03 00 28 25 5d 63 2d f3 |..........(%]c-.| +00000010 a5 91 45 d0 7d 68 39 f6 0e 04 6f 4b c9 dd 4a 54 |..E.}h9...oK..JT| +00000020 f5 a2 04 54 d2 57 4b 40 75 4d 2f b3 5d 00 5b 11 |...T.WK@uM/.].[.| +00000030 89 0e 92 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 90 44 33 |..............D3| -00000010 cf be 4e 29 fc 6f 2f 30 c1 ef aa 8e cb 10 0e f9 |..N).o/0........| -00000020 8f 60 fc 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.`..............| -00000030 80 cb 52 6b e7 c9 45 af 69 6b e8 ee 88 23 61 20 |..Rk..E.ik...#a | -00000040 74 33 |t3| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 0c 9c ab |................| +00000010 24 e8 b2 cf a2 6f f9 8e 54 ed 35 43 07 4d 8f 89 |$....o..T.5C.M..| +00000020 5c 08 15 15 03 03 00 1a 00 00 00 00 00 00 00 02 |\...............| +00000030 f8 65 48 1e a4 03 c0 3b 2f 23 c7 9e 92 59 f6 be |.eH....;/#...Y..| +00000040 b4 a2 |..| diff --git a/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/crypto/tls/testdata/Client-TLSv12-RSA-RC4 index 24a9b8e4155..faa48c78437 100644 --- a/crypto/tls/testdata/Client-TLSv12-RSA-RC4 +++ b/crypto/tls/testdata/Client-TLSv12-RSA-RC4 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 55 02 00 00 51 03 03 7c f1 44 f1 2a |....U...Q..|.D.*| -00000010 6f 7f 62 66 08 15 dd c8 bd 4a 30 b5 a3 73 53 82 |o.bf.....J0..sS.| -00000020 93 78 6b f2 c6 70 70 1e 4d 8f 48 20 24 b3 17 46 |.xk..pp.M.H $..F| -00000030 37 c0 0f 79 af f4 48 43 17 6b ea df 6b 73 07 cf |7..y..HC.k..ks..| -00000040 5f 95 c5 5c 8d b2 99 5c fd 30 e5 1b 00 05 00 00 |_..\...\.0......| +00000000 16 03 03 00 55 02 00 00 51 03 03 c4 5b d6 0f d4 |....U...Q...[...| +00000010 64 3a 37 34 a3 84 9d 3d 1b 33 c3 d4 4f 42 f7 3a |d:74...=.3..OB.:| +00000020 e8 da 8c 8b 97 1a e5 f4 56 a4 bd 20 03 30 25 fd |........V.. .0%.| +00000030 d9 01 7a 7c b8 9d 63 f0 a3 7a 1c 00 6b 75 16 d8 |..z|..c..z..ku..| +00000040 68 5c 7a 8d 4a ae ed 52 fc 92 e5 03 00 05 00 00 |h\z.J..R........| 00000050 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| 00000060 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 00000070 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| @@ -72,15 +73,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| -00000090 01 16 03 03 00 24 fd 67 40 11 7e 4d 8f bb 87 e8 |.....$.g@.~M....| -000000a0 c3 1f e8 b0 15 17 3a f4 6f 5f 87 b2 50 c5 92 e4 |......:.o_..P...| -000000b0 ac c0 c0 98 aa 6f be bc fc 77 |.....o...w| +00000090 01 16 03 03 00 24 83 66 73 cf 08 6f c7 29 1b ea |.....$.fs..o.)..| +000000a0 86 aa 02 66 2d d9 d4 7b 19 0d cc e5 9e dc e9 20 |...f-..{....... | +000000b0 d9 62 82 59 bd e9 91 6b 90 62 |.b.Y...k.b| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 24 e8 ea 6f 8a 0c |..........$..o..| -00000010 79 70 73 a9 7b 2c a8 0a e5 f8 26 f3 eb 05 20 65 |yps.{,....&... e| -00000020 58 9b 0c 8e 28 3d c7 ee cf 57 85 06 a5 d7 46 |X...(=...W....F| +00000000 14 03 03 00 01 01 16 03 03 00 24 ef bb 0c 3b fb |..........$...;.| +00000010 4e 36 53 b9 fa d4 c3 d0 37 5e 2b 22 a2 12 b6 9e |N6S.....7^+"....| +00000020 1c a3 f7 93 74 60 38 18 f1 cc 72 e4 ba 1a 3d |....t`8...r...=| >>> Flow 5 (client to server) -00000000 17 03 03 00 1a 2d 7a c5 d0 12 79 e8 a2 05 d3 a4 |.....-z...y.....| -00000010 51 80 8f 28 37 b9 75 64 f3 11 4c 78 de 0c f3 15 |Q..(7.ud..Lx....| -00000020 03 03 00 16 43 89 2c 8b 9e dc c5 5d 4c ca 7b 4e |....C.,....]L.{N| -00000030 15 e4 e5 62 01 02 b4 d4 6f 1c |...b....o.| +00000000 17 03 03 00 1a 62 a3 b3 3a 89 25 05 89 bc 5a 21 |.....b..:.%...Z!| +00000010 30 61 84 b0 97 52 26 a2 18 87 25 43 17 1a 52 15 |0a...R&...%C..R.| +00000020 03 03 00 16 97 d6 18 0c 30 b3 9b 8f 2b f1 f9 3f |........0...+..?| +00000030 c7 8d a2 e1 ff 36 0c d6 c2 f1 |.....6....| diff --git a/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce b/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce index 0510d5e2d33..868b527396b 100644 --- a/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce +++ b/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 55 71 df 37 76 |....]...Y..Uq.7v| -00000010 48 bb 86 62 66 f1 58 0d 92 f4 c8 bd 17 6c 00 43 |H..bf.X......l.C| -00000020 a9 da f1 6f 19 2c 76 81 6d aa eb 20 4f c7 eb 3f |...o.,v.m.. O..?| -00000030 b8 48 89 7f d8 61 bc e8 3c e6 a0 3d 6c 29 fd 60 |.H...a..<..=l).`| -00000040 7c 0a 09 1c 71 41 07 04 24 dc e7 27 cc a8 00 00 ||...qA..$..'....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 9e b0 dd 2b 97 |....]...Y.....+.| +00000010 86 13 76 2e 65 fc 27 bc fd 01 c0 05 86 b9 e3 bd |..v.e.'.........| +00000020 b9 46 3b 09 37 2a fe 3a eb ee e0 20 65 ad 7c 0b |.F;.7*.:... e.|.| +00000030 1a 0b 9b da b0 8d 56 86 b6 e1 04 1b dd 5d 93 8e |......V......]..| +00000040 a9 ea b6 b7 17 c9 75 26 58 5a c5 37 cc a8 00 00 |......u&XZ.7....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,186 +62,188 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 7a 15 23 |............ z.#| -000002d0 f5 78 c2 16 21 72 bb e5 d3 2e c9 67 55 a8 2c 1f |.x..!r.....gU.,.| -000002e0 00 50 a2 04 4f 71 9a 94 4a 90 55 69 33 08 04 00 |.P..Oq..J.Ui3...| -000002f0 80 53 b3 16 f5 08 3a 5a 84 3c 02 5d c3 b6 0e c2 |.S....:Z.<.]....| -00000300 93 f6 27 74 24 b4 e2 3d 22 04 30 a0 d6 5b c8 da |..'t$..=".0..[..| -00000310 6e 56 30 d4 fb 86 fd 76 8f 1b 47 c0 55 95 cd 15 |nV0....v..G.U...| -00000320 bf a7 27 ce 2d c3 43 6b ed 2d 09 bb eb 55 73 c9 |..'.-.Ck.-...Us.| -00000330 2c ee cd 23 af d9 1c 51 1d 0c 00 14 01 61 8a fd |,..#...Q.....a..| -00000340 8f 95 d1 ce 32 57 ae 2b 09 15 b4 86 41 1e 74 f5 |....2W.+....A.t.| -00000350 d5 96 d7 e1 03 03 09 f4 3c 53 fe 6b 9a c1 52 ab |........>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 bf 35 ae 8c b4 63 82 40 e8 5d d4 |.... .5...c.@.].| -00000040 bb 3d 0a 0f 07 28 3a 74 2c 5b a8 d0 a6 ab 88 ba |.=...(:t,[......| -00000050 7d 5c 1c 42 c7 |}\.B.| +00000030 16 03 03 00 20 5b d2 2a ad 40 50 6f a8 b8 70 d0 |.... [.*.@Po..p.| +00000040 b9 aa ab d5 d7 2a f1 2b f7 d7 9b cd 10 a5 80 e9 |.....*.+........| +00000050 d3 15 3f 4f 00 |..?O.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 e7 86 48 6c 00 |.......... ..Hl.| -00000010 0a 1e f5 5f b8 ff ad 1c 9d 74 24 c5 6e d4 c6 6e |..._.....t$.n..n| -00000020 25 27 7d 6e 18 44 96 29 eb db b0 |%'}n.D.)...| +00000000 14 03 03 00 01 01 16 03 03 00 20 dd 90 d8 8a 0a |.......... .....| +00000010 11 a6 30 9b b0 29 50 c8 b1 70 36 bc fb 84 6e 6d |..0..)P..p6...nm| +00000020 a9 5e 67 3c e2 2e 0b 09 b2 44 38 |.^g<.....D8| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 64 9d 31 09 a1 ce 5a 6d ec 6f c4 |.....d.1...Zm.o.| -00000010 e5 09 df 92 5f d2 1c 7d 62 c4 e7 |...._..}b..| +00000000 17 03 03 00 16 9f e0 6a fc e9 a2 bf cf b4 df 07 |.......j........| +00000010 ba b4 8b 8b 08 ca bd a7 d5 02 2a |..........*| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 9b cb 75 61 99 76 30 9c 14 a5 12 |.......ua.v0....| -00000010 92 de b7 95 cc 8f fe ad f1 |.........| +00000000 16 03 03 00 14 ed 9b 22 44 dd b2 e2 c3 7e ab 0c |......."D....~..| +00000010 69 98 d0 7b 40 9e da e2 67 |i..{@...g| >>> Flow 7 (client to server) -00000000 16 03 03 01 1a c7 9a be e1 2a 62 9f 01 59 e9 6a |.........*b..Y.j| -00000010 5f d6 32 88 bd 39 76 1b 34 fd 39 8d c7 31 cb 97 |_.2..9v.4.9..1..| -00000020 c6 09 8b 00 c9 f3 f9 00 c5 b6 48 e1 28 ae b8 8b |..........H.(...| -00000030 b2 f0 eb 8b cb e8 68 30 50 b5 23 ba cf f3 8d f3 |......h0P.#.....| -00000040 47 5f 94 ac fb 5e 56 9e 5a f8 e7 12 60 13 83 9c |G_...^V.Z...`...| -00000050 34 ca 45 a7 63 5f 2c 6e 46 c8 5a a0 d3 5b 9a a6 |4.E.c_,nF.Z..[..| -00000060 70 be da df 9e 79 21 98 bd fb 94 01 6d 14 f4 5c |p....y!.....m..\| -00000070 2a 13 56 26 47 33 7d 4f ab 5a fc 9c 9e 8d f4 75 |*.V&G3}O.Z.....u| -00000080 d0 64 16 ba f2 0d 04 ca 5d 94 6b da a8 09 b1 29 |.d......].k....)| -00000090 70 a9 37 1e ac 94 e3 81 60 c3 19 f3 a9 99 6a 11 |p.7.....`.....j.| -000000a0 b1 e7 23 45 8a f5 42 f5 50 76 9f 1e 9e a8 e7 75 |..#E..B.Pv.....u| -000000b0 4a 18 84 80 da 10 ed 83 9a 14 a9 a1 90 54 8e 8b |J............T..| -000000c0 d1 32 83 6d e7 7e be 59 f4 66 59 53 75 37 c6 82 |.2.m.~.Y.fYSu7..| -000000d0 15 aa 56 0a 01 e1 11 ba 64 0c 8e 44 93 60 29 a4 |..V.....d..D.`).| -000000e0 cc 9f b0 b9 d5 df 9c aa 64 2c ef 0c 9a 18 2a 97 |........d,....*.| -000000f0 e1 20 07 37 35 28 97 9d 00 53 61 11 81 22 45 9e |. .75(...Sa.."E.| -00000100 c3 d7 b2 b3 4c f2 05 5b e6 a4 de 11 7f a7 a2 82 |....L..[........| -00000110 88 1c cb d9 24 80 3d 34 0c fc 22 58 32 28 1b |....$.=4.."X2(.| +00000000 16 03 03 01 34 0d de 90 41 3c 76 1d 54 9d c2 7e |....4...A?J..}......| +00000070 4c 1c fb 2c 88 4c 13 8d c8 d0 e3 7f f6 cb 2e ca |L..,.L..........| +00000080 cb 92 ae 30 fe ea 3c 3e ae 57 51 6a d6 98 5c d6 |...0..<>.WQj..\.| +00000090 19 85 72 bd 62 56 fa c2 ea 08 eb b4 d9 75 ac de |..r.bV.......u..| +000000a0 a5 40 8d 8b 1f c4 8f f6 6d b2 5f d1 6d fb 14 fa |.@......m._.m...| +000000b0 e2 92 9e 04 37 d3 60 83 28 4a f9 92 8c b3 4a d2 |....7.`.(J....J.| +000000c0 ce 6d 95 e4 40 79 7c 3d 98 11 e7 da 5c 56 0a 95 |.m..@y|=....\V..| +000000d0 e0 6f 36 80 07 da 29 ef 88 44 db cd 2b 5a a5 27 |.o6...)..D..+Z.'| +000000e0 56 5a 94 49 aa 51 ae 48 f9 12 8d df e0 2a a7 67 |VZ.I.Q.H.....*.g| +000000f0 7f 55 3e 7a b6 bb 28 e3 a8 d9 44 67 e9 03 8f e5 |.U>z..(...Dg....| +00000100 2b 40 a3 37 fb e4 51 0a 18 8f bb 14 2e 5b 62 93 |+@.7..Q......[b.| +00000110 ab a4 40 d7 5f 15 12 cf 93 74 37 d0 ec 14 d3 a3 |..@._....t7.....| +00000120 eb 6f 61 35 4a c4 b5 d7 d1 bb ae fe 11 6d 04 ac |.oa5J........m..| +00000130 58 72 a6 72 b6 06 9d 93 a5 |Xr.r.....| >>> Flow 8 (server to client) -00000000 16 03 03 00 85 ba 55 5d 15 b8 6d 8a b6 82 a8 e1 |......U]..m.....| -00000010 88 ea fe c0 a6 a8 fe 78 ed 8b ae 44 eb 7b 6c cc |.......x...D.{l.| -00000020 0f ad a1 da da 86 fb 60 07 4a 0e 5c ba 36 09 8b |.......`.J.\.6..| -00000030 95 3f f0 87 26 0f 7a e7 7c 1f af c7 67 42 c9 39 |.?..&.z.|...gB.9| -00000040 39 6a 4d 8d 87 00 3b 14 76 4a 86 87 46 1e d4 04 |9jM...;.vJ..F...| -00000050 2d ea c1 44 1f e8 87 71 da 1e 26 72 a2 e9 40 0c |-..D...q..&r..@.| -00000060 33 6e 6f 06 43 ed 7f fc 8f 4c d4 f4 0f 83 19 cb |3no.C....L......| -00000070 52 a9 94 f3 6a 64 db dd 20 d1 a7 d4 c7 6e 86 ed |R...jd.. ....n..| -00000080 6e ea 5c 66 d1 34 a6 92 7e b1 16 03 03 02 69 48 |n.\f.4..~.....iH| -00000090 13 97 82 60 46 e1 c9 02 d2 e1 f3 62 da d6 3a c1 |...`F......b..:.| -000000a0 2a a7 47 bd c2 ee 09 d5 2d 7e 5e 35 09 79 88 35 |*.G.....-~^5.y.5| -000000b0 96 50 09 68 79 e9 de e1 71 97 11 60 c5 4e 84 54 |.P.hy...q..`.N.T| -000000c0 03 78 69 84 e3 7f 02 1a 58 04 ed 53 47 01 b6 9e |.xi.....X..SG...| -000000d0 bd 5f 77 34 e7 52 3b 73 45 e1 10 3f c8 6e 4c 09 |._w4.R;sE..?.nL.| -000000e0 d0 4b 79 f8 de 0f 15 e7 2d 42 5d 7a 89 80 1f fb |.Ky.....-B]z....| -000000f0 f9 02 6f a1 72 d4 8d 65 8e d0 a8 43 41 4c 48 57 |..o.r..e...CALHW| -00000100 71 21 b3 14 45 e5 b1 f5 55 7a dd 89 c3 0f af 27 |q!..E...Uz.....'| -00000110 03 d6 5c 2d bc 24 5b 51 fa ae 34 7b f9 56 e8 41 |..\-.$[Q..4{.V.A| -00000120 cd 77 1c 3d c8 45 f5 a5 4a 97 92 ff bb cd 5b ff |.w.=.E..J.....[.| -00000130 d5 33 d6 02 9b 2a 5a 3a e4 1b fb 48 34 b3 0b ce |.3...*Z:...H4...| -00000140 d7 34 5c 4a b4 4b bd 87 b6 72 40 ab 29 b0 65 25 |.4\J.K...r@.).e%| -00000150 c7 1d 71 b6 e2 d7 b1 23 b1 96 a6 bd 74 eb ad 69 |..q....#....t..i| -00000160 59 0c 0f af 8a 64 be e4 a7 27 c2 95 11 05 55 a1 |Y....d...'....U.| -00000170 d6 44 df ad 1d 9c 3a 88 24 52 52 9d 42 f2 74 98 |.D....:.$RR.B.t.| -00000180 08 9f 55 1b 2f 79 ca b4 63 38 e4 f2 fa 99 ce 66 |..U./y..c8.....f| -00000190 77 ac 8d 31 91 05 1c bc 51 0a 31 df 5d 3e f8 69 |w..1....Q.1.]>.i| -000001a0 b7 fa f2 35 af 57 6d 7b c3 bf 1d 98 21 40 dd 02 |...5.Wm{....!@..| -000001b0 1c de ac 02 40 c8 d6 04 23 30 71 16 d0 0a 26 29 |....@...#0q...&)| -000001c0 66 e9 f1 a8 76 f8 52 18 3e 3f c5 66 c9 11 04 6c |f...v.R.>?.f...l| -000001d0 32 1b 35 cc 9a 34 70 07 da db 12 51 78 77 dc bc |2.5..4p....Qxw..| -000001e0 7a bb b8 b9 06 79 bb 04 dd d4 46 8e b5 69 d5 39 |z....y....F..i.9| -000001f0 5e 34 8e 37 dd a2 3e 31 be 28 19 45 21 76 5b dc |^4.7..>1.(.E!v[.| -00000200 7d 25 a2 41 98 16 1b 5b 69 f0 90 f9 28 a8 e9 b5 |}%.A...[i...(...| -00000210 6f 00 e3 3e eb f6 f3 e4 c9 0f bb 74 ce 40 23 df |o..>.......t.@#.| -00000220 12 c6 78 b0 2e bb 68 96 04 a3 e3 43 6b 4b c3 37 |..x...h....CkK.7| -00000230 6d 97 c6 79 1a ff 4f 00 c7 76 64 5c b8 b3 17 20 |m..y..O..vd\... | -00000240 3c 3e 6b d5 2b 72 88 11 73 1e 63 a7 6f 1e ae 83 |<>k.+r..s.c.o...| -00000250 10 77 6f d1 96 86 84 63 fd 27 8e b9 54 da 4b b5 |.wo....c.'..T.K.| -00000260 56 f0 50 8a aa c7 e1 b3 cb 9c 36 9e ec 38 31 39 |V.P.......6..819| -00000270 78 ec ea 34 8a 87 cf 6b 34 fd 5e 81 92 81 61 f1 |x..4...k4.^...a.| -00000280 88 e7 50 62 2e 58 0b d9 b9 ca f3 ed 79 a9 9a 01 |..Pb.X......y...| -00000290 80 9d 7f 84 ae de fb 51 ac 0f 6b b9 76 fd 68 d4 |.......Q..k.v.h.| -000002a0 f4 8d c3 92 6b 5e 9e 99 ff 7a f4 b7 0e ec 0d e7 |....k^...z......| -000002b0 6b 24 75 fb 21 49 6f 5b 31 12 f2 88 8e 3b b4 34 |k$u.!Io[1....;.4| -000002c0 f2 f7 c6 e7 48 0e d6 1d 81 11 32 16 01 cb b7 7f |....H.....2.....| -000002d0 a6 bd 9c 87 8c 0f 12 b2 dc 73 5d a0 46 fd f3 e8 |.........s].F...| -000002e0 b8 6f e4 38 ab 94 96 a8 bd ed 90 0e 31 1f fc 2f |.o.8........1../| -000002f0 8f 50 e2 97 6a f5 5c b4 16 03 03 00 bc 65 bb 7c |.P..j.\......e.|| -00000300 42 03 0d 42 46 e3 ac 9f 8a 96 b6 a3 f4 cf a5 30 |B..BF..........0| -00000310 5b 02 17 dc 20 7d 18 19 21 a4 70 f4 4b 99 bf b5 |[... }..!.p.K...| -00000320 cd d7 07 59 a5 82 ed 85 03 06 5c 34 3f c8 c3 4d |...Y......\4?..M| -00000330 c3 fb 96 05 bf b5 bd bf e2 28 07 7e 51 a6 84 90 |.........(.~Q...| -00000340 bf 9e 2e f6 b5 04 8e 06 7a 63 c8 00 84 a1 a3 2c |........zc.....,| -00000350 f3 6f 52 52 c4 ce 4a 59 31 1f d4 ab 2e f4 75 90 |.oRR..JY1.....u.| -00000360 a5 3b ff ab 20 be 51 92 c5 f4 4d 8b f2 2a a7 ff |.;.. .Q...M..*..| -00000370 90 07 40 3e d6 9c cf 23 54 d1 65 d3 74 79 af 51 |..@>...#T.e.ty.Q| -00000380 31 35 40 aa 29 42 32 7e 42 2d af 79 e8 59 6a 10 |15@.)B2~B-.y.Yj.| -00000390 c5 55 6b 70 53 53 ab 02 48 ba 1f df 07 59 f8 34 |.UkpSS..H....Y.4| -000003a0 ee 1d d3 e9 12 86 8b 37 2b cc 27 78 fe e1 65 2b |.......7+.'x..e+| -000003b0 c3 1e f2 25 a4 6d 3c b1 d4 16 03 03 00 4a 50 98 |...%.m<......JP.| -000003c0 cd ee ab 2c 94 95 d6 46 06 ef 63 65 5c aa 6d 6e |...,...F..ce\.mn| -000003d0 fb a0 99 62 23 af 7a 7d 17 dc a3 c6 2b 9a 56 2e |...b#.z}....+.V.| -000003e0 b8 60 87 1e 88 5d 58 27 3f 02 b4 f5 2f 3b 17 8c |.`...]X'?.../;..| -000003f0 f9 93 0c a9 58 af 11 ed 27 9d af a5 0a 2b d6 55 |....X...'....+.U| -00000400 7e c4 54 4a 36 51 b7 7b 16 03 03 00 14 c1 c4 d7 |~.TJ6Q.{........| -00000410 ea 2d f0 8c 54 0e 19 33 e1 7e a8 ae 49 7c 5e 05 |.-..T..3.~..I|^.| -00000420 23 |#| +00000000 16 03 03 00 85 8b 8d 61 42 37 50 ee 69 d8 fb e9 |.......aB7P.i...| +00000010 89 a4 04 63 5d 87 a4 31 cc 22 26 c0 2c 22 1a 73 |...c]..1."&.,".s| +00000020 cc f0 9f be 65 c4 e0 ad 6d b0 b5 d3 86 2c 0b 59 |....e...m....,.Y| +00000030 e6 ae 58 38 b5 5f 4f 6e 7c ec e9 27 23 5f 4a 92 |..X8._On|..'#_J.| +00000040 78 5f cc 9f 7f 2b bb 2c dd 04 17 ea d4 87 b9 6d |x_...+.,.......m| +00000050 d0 1e 35 01 b4 4d 5d 73 6a 9f de 1d 71 47 78 d6 |..5..M]sj...qGx.| +00000060 89 dc c2 d6 5c 69 0c dc bb 7b 59 60 56 47 e9 5c |....\i...{Y`VG.\| +00000070 04 3e 3c 93 18 9b 40 4b 95 1f 20 e3 17 c6 ab 35 |.><...@K.. ....5| +00000080 db 3f 88 d7 4b 89 5a 53 b7 a9 16 03 03 02 69 85 |.?..K.ZS......i.| +00000090 49 cc 00 5a 45 40 9d be 80 06 97 16 a0 c0 dc bb |I..ZE@..........| +000000a0 32 62 18 88 31 3b 14 ec 9d f2 3f ed c0 36 ad bb |2b..1;....?..6..| +000000b0 69 fa 32 f5 13 54 2b 77 f3 db 6e 20 0a 2b 5c a5 |i.2..T+w..n .+\.| +000000c0 d8 aa 5a 63 8d c1 51 50 41 f6 6c f7 ef 2f 15 81 |..Zc..QPA.l../..| +000000d0 85 af 6e e5 01 95 9a 5e 70 26 cb c1 c8 89 3f b8 |..n....^p&....?.| +000000e0 3d 5a 1b 68 a6 25 08 48 ad dd 29 db bf ce 75 44 |=Z.h.%.H..)...uD| +000000f0 ca cd 92 79 47 d8 25 f1 23 9a 63 62 15 05 d8 2c |...yG.%.#.cb...,| +00000100 c0 30 a4 65 a7 f9 89 a4 fe 87 32 21 07 24 d9 16 |.0.e......2!.$..| +00000110 64 26 48 75 ab a7 00 e1 9b 48 5c 77 3d 66 18 69 |d&Hu.....H\w=f.i| +00000120 35 a9 4c 03 f5 9f 42 ff 50 98 73 b1 82 16 fd ff |5.L...B.P.s.....| +00000130 94 fd aa 3c 46 1f b5 99 fd de ab 2e 6a 24 00 5a |.........."| +00000300 3d 8d 48 5d 28 cd ae 94 db 95 2e a6 44 77 da d5 |=.H](.......Dw..| +00000310 a1 09 7c a3 4c 3f a6 18 80 92 cf 5c 77 9d 18 5d |..|.L?.....\w..]| +00000320 43 78 05 bb cb 8e 27 7c cc 2e 9c 54 95 ff 1c 74 |Cx....'|...T...t| +00000330 48 fb df 47 e8 e1 24 94 94 5d cc 2c b2 df 48 6c |H..G..$..].,..Hl| +00000340 22 1e 61 f1 e3 c6 56 fb 79 70 b0 ab c5 70 ca 7f |".a...V.yp...p..| +00000350 c0 32 8d 6d a5 55 6d 94 8c 7b 9d da 0b 35 d1 da |.2.m.Um..{...5..| +00000360 77 85 01 66 15 be 10 c3 3c 9b 80 61 b3 c0 1a 29 |w..f....<..a...)| +00000370 22 d1 d1 ba 4a ea 01 58 72 94 79 f0 6e 5f 36 23 |"...J..Xr.y.n_6#| +00000380 8a cf 16 fa 2c 5f 6d dd 54 61 df bc 6f 91 d4 df |....,_m.Ta..o...| +00000390 e7 6f 50 8f 9c 27 04 04 19 80 10 a2 8d a5 61 81 |.oP..'........a.| +000003a0 06 1f b0 79 87 c0 95 87 f7 d8 87 22 75 a5 87 30 |...y......."u..0| +000003b0 f4 33 6d cb 59 f7 18 75 0f 16 03 03 00 4a d3 e9 |.3m.Y..u.....J..| +000003c0 2e 47 65 f2 29 70 4c 74 3f e9 13 88 e7 66 c6 73 |.Ge.)pLt?....f.s| +000003d0 0f e4 7a 8f 0e 49 49 39 90 e7 ff d4 1f 8a d6 c6 |..z..II9........| +000003e0 91 16 f6 a6 fe 60 d8 ba 26 a6 5e 44 f5 76 88 63 |.....`..&.^D.v.c| +000003f0 10 d0 89 2f 6b ae 55 64 13 0c 63 76 69 df 6a 4a |.../k.Ud..cvi.jJ| +00000400 74 15 51 0b 4d 74 db 49 16 03 03 00 14 f2 0f e7 |t.Q.Mt.I........| +00000410 38 90 33 ff 5e 20 60 42 32 40 72 2c c8 70 d7 ba |8.3.^ `B2@r,.p..| +00000420 a1 |.| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 83 ef 87 6b aa f1 2a cc c1 b8 5d |....i...k..*...]| -00000010 47 e4 2d da c5 91 62 e4 7d 49 da 54 a3 79 fb 1d |G.-...b.}I.T.y..| -00000020 59 49 e8 a6 ab 79 c0 9f 51 f9 d2 63 0d 8c 6b 7f |YI...y..Q..c..k.| -00000030 b6 77 2d f3 b3 3e 78 86 3a 14 1a ab 3b 5e 23 b2 |.w-..>x.:...;^#.| -00000040 d3 5c b1 2b 5c f4 f0 9d e2 87 08 d0 2f 24 30 d3 |.\.+\......./$0.| -00000050 05 eb f8 a6 b2 d1 52 00 c3 9e 0b 82 34 3e fd 5a |......R.....4>.Z| -00000060 46 d5 b6 b2 f0 a0 96 11 e1 35 c2 32 57 d6 dd b2 |F........5.2W...| -00000070 a8 ad b2 71 a2 6f 83 05 d6 f1 83 38 a0 3c 13 ff |...q.o.....8.<..| -00000080 c1 c1 b0 1e b5 40 5b b5 05 31 65 0b 81 a6 b0 37 |.....@[..1e....7| -00000090 7d 16 3b 7b cb e7 58 7f 81 25 e3 39 37 98 87 b0 |}.;{..X..%.97...| -000000a0 e1 8f c0 d5 de 33 fe de 15 37 41 25 d8 97 5d 84 |.....3...7A%..].| -000000b0 28 12 b4 a5 b0 15 f1 f4 cf 41 28 e9 26 5d ba 36 |(........A(.&].6| -000000c0 da b6 a6 cb 21 92 21 30 4b 21 4d 44 28 4d 76 d1 |....!.!0K!MD(Mv.| -000000d0 61 65 fa 02 05 67 50 ec 7d 98 78 21 46 5d fe 75 |ae...gP.}.x!F].u| -000000e0 78 8e 9d 41 6a 0a d7 0e 27 22 d0 a1 21 57 3d 23 |x..Aj...'"..!W=#| -000000f0 d1 7d 08 f4 0b 1b 90 ec 63 74 4c e7 df c8 8f 8b |.}......ctL.....| -00000100 b8 cd 2b 06 a5 35 f5 c1 62 d5 46 f3 d5 19 5b ce |..+..5..b.F...[.| -00000110 c8 d2 f4 c1 51 5f cd b2 51 23 61 bf 93 7f 5d bd |....Q_..Q#a...].| -00000120 61 f2 b2 e0 ad be ab d7 c9 77 26 c2 61 fb 25 8d |a........w&.a.%.| -00000130 46 38 7a 30 48 9f b5 5c 47 6b ce 10 1d 03 d0 68 |F8z0H..\Gk.....h| -00000140 7f 00 c0 94 f4 35 eb 41 e8 91 f6 d9 5c 44 d6 79 |.....5.A....\D.y| -00000150 72 9f 22 a4 08 fd 74 1b 42 dc 49 06 34 8f b6 f5 |r."...t.B.I.4...| -00000160 12 1c 09 f0 d4 eb e4 6e d5 9a 31 f9 1a 88 c1 bf |.......n..1.....| -00000170 37 42 90 5f c8 e1 38 2b 8b 4b c1 cd 66 72 e6 49 |7B._..8+.K..fr.I| -00000180 d3 19 0e 01 19 60 f7 7d d3 66 b2 bf bd 94 30 c9 |.....`.}.f....0.| -00000190 3a 01 aa b6 dc 2a d6 1a 68 cf a6 31 5e 9a 1d 5b |:....*..h..1^..[| -000001a0 90 bb 77 33 31 f2 28 5a 70 a5 c5 ef 91 91 27 22 |..w31.(Zp.....'"| -000001b0 59 33 d5 22 78 8e 8f 07 91 3c 69 ec b9 81 be e8 |Y3."x.........G...NWQ.Y| -00000250 05 84 dc 4d fd fb d1 11 33 b6 e5 5e df 65 d4 ed |...M....3..^.e..| -00000260 04 af 89 b3 f0 90 9b 7c 5e 83 b1 66 71 b1 16 03 |.......|^..fq...| -00000270 03 00 35 5b 37 fa e1 97 11 25 7c fd da 7e e8 2a |..5[7....%|..~.*| -00000280 9b 28 fa 20 a6 9b 9b ca 99 ed a2 eb 5b 84 df a0 |.(. ........[...| -00000290 b9 14 c2 fe 38 a8 54 06 e4 54 38 87 2a 24 8b 1e |....8.T..T8.*$..| -000002a0 3e ba 0a bb c2 1d a4 74 16 03 03 00 98 8b 39 c7 |>......t......9.| -000002b0 ac e5 80 bf 49 95 ad f4 c0 cf c9 7c 86 bf 11 65 |....I......|...e| -000002c0 53 40 f3 64 3e 04 ad c9 8d 33 8a 10 4a f5 2e c5 |S@.d>....3..J...| -000002d0 22 18 59 1c 81 65 8a 51 47 b4 8d b1 94 57 3c f8 |".Y..e.QG....W<.| -000002e0 d0 06 60 ce 04 f9 50 8f 6c 43 d8 6e b0 9e d9 da |..`...P.lC.n....| -000002f0 4b e5 b5 05 b7 1b 4b 46 59 d6 ad 20 bb 4c fc aa |K.....KFY.. .L..| -00000300 9a 9b ef fd 59 4b 2a 63 01 b0 1b 2d ed b1 f4 5b |....YK*c...-...[| -00000310 bb ca cd fa 13 06 06 7e 1d a5 cd c3 ca 4e bf 7b |.......~.....N.{| -00000320 7e 92 92 09 61 35 68 a2 38 f9 13 41 f4 a9 a5 0f |~...a5h.8..A....| -00000330 42 63 e4 15 e8 86 00 48 90 2b 43 30 da 05 b6 fc |Bc.....H.+C0....| -00000340 8e 7f 52 d3 b8 14 03 03 00 11 82 73 be a9 08 9d |..R........s....| -00000350 5b 2f fe bd 1f 2c fb e2 f3 94 f3 16 03 03 00 20 |[/...,......... | -00000360 d0 47 0f 2d 7e ce 8f 01 e2 7d 01 3c 32 79 a0 26 |.G.-~....}.<2y.&| -00000370 fe 00 ce d3 37 46 20 b4 f8 af 21 81 0f 1e ba 2d |....7F ...!....-| +00000000 16 03 03 02 69 78 39 27 1a 64 94 f7 9c 64 ac 37 |....ix9'.d...d.7| +00000010 28 be d0 a4 74 98 34 51 8e 3b c7 14 02 83 ee a5 |(...t.4Q.;......| +00000020 05 55 59 f8 04 43 59 cd 33 e6 c4 44 57 30 68 db |.UY..CY.3..DW0h.| +00000030 b2 cb 50 db c1 e6 c4 04 a3 79 22 40 15 f9 89 57 |..P......y"@...W| +00000040 7b 7a 68 d6 d1 15 c9 7f 6b d8 3a 6c dc 32 4f 72 |{zh.....k.:l.2Or| +00000050 97 57 32 25 f9 78 e6 07 91 f4 45 67 b1 41 dd f9 |.W2%.x....Eg.A..| +00000060 5b fd 76 53 d5 7d 0f 74 6e 2e ea d9 9c 2d 00 39 |[.vS.}.tn....-.9| +00000070 2f 7f 49 97 24 bf e4 f2 c7 7e 21 f9 dd 30 3a 78 |/.I.$....~!..0:x| +00000080 3c 53 41 58 5c 97 3a ff 6f 60 f4 b6 d6 23 a9 ad |.c....| +000000e0 6c b5 0d 0c d3 c6 6d 47 2e a8 3a d8 ec fd d3 42 |l.....mG..:....B| +000000f0 ef 8b e8 75 a6 04 06 3b 5e 57 ae a3 10 2e 6d 01 |...u...;^W....m.| +00000100 0e ea 94 e6 78 1b 91 f0 a0 1e 55 d3 25 13 15 ac |....x.....U.%...| +00000110 eb a4 7c c3 66 83 62 00 a3 d2 f5 7c 64 c6 39 fb |..|.f.b....|d.9.| +00000120 6d ee 01 50 d4 13 5d 10 5f 31 30 09 90 91 64 ad |m..P..]._10...d.| +00000130 f1 c5 4b ed 9d ef 2a 71 e5 7a b2 5d a8 57 bc b8 |..K...*q.z.].W..| +00000140 1f 32 c6 f0 61 f0 08 9e 07 9b d3 99 5b 5e a5 32 |.2..a.......[^.2| +00000150 1f 8a f7 30 1f e9 e6 39 b1 5a c6 a5 22 c8 98 49 |...0...9.Z.."..I| +00000160 04 f2 58 4d e2 15 e6 cd d1 2b 05 54 81 cc b8 33 |..XM.....+.T...3| +00000170 5d 26 52 65 95 32 84 01 f6 05 fa 19 58 c6 57 53 |]&Re.2......X.WS| +00000180 c8 d7 3d ef 56 4e 6e e4 17 45 1c bc 40 ee 06 32 |..=.VNn..E..@..2| +00000190 60 74 9e 62 02 47 52 a8 92 57 26 1f ba 2d 93 67 |`t.b.GR..W&..-.g| +000001a0 94 46 0f c4 0d f5 df 75 b0 d9 27 02 56 f3 82 e1 |.F.....u..'.V...| +000001b0 da 1c 3b 3e 97 93 c8 2d 12 bd b4 5b 36 7a 5c bf |..;>...-...[6z\.| +000001c0 27 9a 75 11 f9 4d 9b c0 ae 6b be 71 5f 37 33 b5 |'.u..M...k.q_73.| +000001d0 4e d4 5a fb 98 71 c5 77 8c fc e2 f3 91 73 35 f4 |N.Z..q.w.....s5.| +000001e0 e7 13 b1 ea bd c2 a9 46 b9 ea 88 06 58 a2 49 a2 |.......F....X.I.| +000001f0 97 2b cf 1b 25 a3 71 a0 22 95 4c 54 81 eb 41 7f |.+..%.q.".LT..A.| +00000200 80 15 82 ec 19 0c f8 a3 21 fe 37 2e e1 ca 34 02 |........!.7...4.| +00000210 5d ec 78 d9 eb 99 93 5d 96 26 cd 4c 56 3a 35 6a |].x....].&.LV:5j| +00000220 7f d0 0c c7 b7 c3 80 c6 fe d0 04 54 00 8c 4c 8b |...........T..L.| +00000230 43 f4 36 b8 ea 51 35 3c 5e b5 b9 45 dc d2 19 bd |C.6..Q5<^..E....| +00000240 d2 2a 95 bc 7f 22 43 4f 84 be bd 7b ab a8 5c 4d |.*..."CO...{..\M| +00000250 28 99 e6 e5 05 33 05 38 be 17 55 80 2d e1 de cf |(....3.8..U.-...| +00000260 39 4e 5b 7d 89 b4 a6 d3 0a e3 fd 47 e1 2c 16 03 |9N[}.......G.,..| +00000270 03 00 35 f3 2d 2c 7b fa 06 39 06 40 27 5b ea 9e |..5.-,{..9.@'[..| +00000280 2f 4a 6c 32 df 62 c3 bc af ed 21 6a 1a 34 82 cf |/Jl2.b....!j.4..| +00000290 73 e5 b9 1d 8d 42 3d 8e b7 e6 1c 0a e0 81 3e cd |s....B=.......>.| +000002a0 88 23 f3 56 55 09 e2 6e 16 03 03 00 98 73 0f 59 |.#.VU..n.....s.Y| +000002b0 0e 1b 1b d1 db db 6d 47 d9 05 f8 e1 29 32 e5 16 |......mG....)2..| +000002c0 f9 f6 24 2b 0f 2d bb 74 da fd 75 9b ec 6a 3f 02 |..$+.-.t..u..j?.| +000002d0 c8 3a ab 23 ec cb 77 c6 d7 7b ba ce 29 85 66 54 |.:.#..w..{..).fT| +000002e0 ab df c9 74 2a 50 b5 cd 45 03 e2 ce 6f d3 d0 f1 |...t*P..E...o...| +000002f0 1a 3e e4 c0 34 72 e1 53 1e 69 9a d7 41 4f d4 3a |.>..4r.S.i..AO.:| +00000300 31 af 1a 0b 83 82 e7 6c 4f f6 9a d5 84 bb 9a 14 |1......lO.......| +00000310 e3 ec 04 12 c8 83 9c c8 d9 81 c1 c9 16 db 35 6e |..............5n| +00000320 0f af a0 b3 e6 a9 2b ad a5 1f cd a0 fb 45 01 84 |......+......E..| +00000330 ae b5 42 49 21 d8 29 06 0a 0e e8 26 8e f4 f1 56 |..BI!.)....&...V| +00000340 c2 7c 8f d6 4a 14 03 03 00 11 c6 06 37 68 e0 2b |.|..J.......7h.+| +00000350 dd 32 2a b5 c7 b6 ad e2 c8 7c d8 16 03 03 00 20 |.2*......|..... | +00000360 1d 80 95 df 2d d3 38 50 a2 2d bc 09 50 e4 e8 47 |....-.8P.-..P..G| +00000370 5f 3e 26 03 5e d3 9b 5a ee ed d4 bb cb da 05 5b |_>&.^..Z.......[| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 53 7f 72 ce 10 f4 0e a3 ed ed 8d |.....S.r........| -00000010 3a ad 2d 57 c8 e1 16 03 03 00 20 11 e9 69 5e ff |:.-W...... ..i^.| -00000020 22 0d f6 a3 e1 e5 3f 14 34 a0 33 d7 d5 0a 7f bc |".....?.4.3.....| -00000030 7c 69 9b 9a d2 aa 41 87 fe da de 17 03 03 00 19 ||i....A.........| -00000040 bd a1 83 5d 27 9f cc 0b 40 02 23 6e 6f 18 4c bc |...]'...@.#no.L.| -00000050 48 c4 02 7d 45 08 71 ac d7 |H..}E.q..| +00000000 14 03 03 00 11 13 75 b3 44 ec 4c 6b 24 d3 52 90 |......u.D.Lk$.R.| +00000010 28 c1 47 92 5c 0d 16 03 03 00 20 c2 61 ed 34 d2 |(.G.\..... .a.4.| +00000020 c5 cf fd b3 31 3d 1d 5f 30 87 18 65 01 47 da 0f |....1=._0..e.G..| +00000030 d9 eb 4f 0f 50 2e 02 86 fe eb 13 17 03 03 00 19 |..O.P...........| +00000040 3f ac 26 1c 16 0e 16 bf b1 d3 80 86 dd c6 e2 b6 |?.&.............| +00000050 3f 5a 0b 0c 3e 7d 3b a8 d5 |?Z..>};..| >>> Flow 11 (client to server) -00000000 15 03 03 00 12 80 ae fb 45 cb a1 2d 1f c8 b6 02 |........E..-....| -00000010 3a 28 62 d6 13 48 2c |:(b..H,| +00000000 15 03 03 00 12 ea 81 9d df ec c1 0c 3d 21 8b fe |............=!..| +00000010 b5 24 d8 92 43 1d 3d |.$..C.=| diff --git a/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice b/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice index 7ff58763c5b..e83ad4b285c 100644 --- a/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice +++ b/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 25 9f b0 d0 c5 |....]...Y..%....| -00000010 56 c8 79 6a 1a ff 0e e9 8b 41 b6 be c7 36 0b 58 |V.yj.....A...6.X| -00000020 c0 9e 9d 6c 4c b4 39 1f 95 ff 8f 20 32 27 d2 39 |...lL.9.... 2'.9| -00000030 ac f6 33 f9 48 a4 0b 0f e1 f9 5f 0a 83 7b 75 95 |..3.H....._..{u.| -00000040 23 55 14 ba 55 2f 47 42 e8 df 09 39 cc a8 00 00 |#U..U/GB...9....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 36 29 60 e0 b5 |....]...Y..6)`..| +00000010 ee 59 a6 3b 1a de 96 8a 51 0c c1 15 30 ce 6a 70 |.Y.;....Q...0.jp| +00000020 ca 5b fa a5 86 f4 59 79 44 cd 73 20 ad b7 a9 d5 |.[....YyD.s ....| +00000030 c1 aa a6 49 6d a8 36 a9 bf 40 1e 3a d4 2c 21 4a |...Im.6..@.:.,!J| +00000040 5d aa fa 75 80 d4 cb fc be 2b 41 36 cc a8 00 00 |]..u.....+A6....| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,286 +62,290 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2b 66 1d |............ +f.| -000002d0 80 f2 60 32 0f af 6f d3 03 db 28 c1 33 18 1c 5d |..`2..o...(.3..]| -000002e0 71 fd 2a 24 f9 3c 4d 76 ca e3 93 8d 25 08 04 00 |q.*$.{W...*| +00000350 85 0d b0 5f bf a5 8e 74 55 72 dc 2c 5c 60 52 93 |..._...tUr.,\`R.| +00000360 1e 28 9d 36 9f fd da a5 3b 51 96 4e 12 d6 d4 ca |.(.6....;Q.N....| +00000370 d3 16 03 03 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 7b de 6f c8 b7 f1 69 89 0b 29 af |.... {.o...i..).| -00000040 62 1b 92 47 e9 44 f7 26 91 93 9c 3b e2 77 0e d0 |b..G.D.&...;.w..| -00000050 c5 af fd e5 59 |....Y| +00000030 16 03 03 00 20 e4 80 79 12 42 80 88 c3 66 6b 9b |.... ..y.B...fk.| +00000040 a2 03 59 f9 a3 54 2f 7f 03 de 90 97 1d cb 48 08 |..Y..T/.......H.| +00000050 19 a4 bb 13 64 |....d| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 94 da e2 2e f3 |.......... .....| -00000010 65 59 31 4f 58 42 57 b5 1f e6 c1 5a c6 07 97 12 |eY1OXBW....Z....| -00000020 f6 6c 20 cc 91 50 76 42 70 dd 2c |.l ..PvBp.,| +00000000 14 03 03 00 01 01 16 03 03 00 20 9e 59 22 68 f2 |.......... .Y"h.| +00000010 3c 38 7d cf 43 eb 77 73 94 6c 35 e5 3f 3e 7e 03 |<8}.C.ws.l5.?>~.| +00000020 29 96 e8 c6 f7 5c b4 39 c3 77 61 |)....\.9.wa| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 fe 0d 78 61 f9 fe 65 3c 42 c0 98 |.......xa..e>> Flow 6 (server to client) -00000000 16 03 03 00 14 e0 bb 6e cc 69 fc a7 02 46 c4 5e |.......n.i...F.^| -00000010 a5 b1 1e ce e9 c7 7a d9 76 |......z.v| +00000000 16 03 03 00 14 a8 ab 9e 3c 00 e4 6f b3 26 dd 3a |........<..o.&.:| +00000010 67 ab ee 28 a0 a1 65 83 91 |g..(..e..| >>> Flow 7 (client to server) -00000000 16 03 03 01 1a a7 03 1c ef 27 0a 04 9b 31 b0 c6 |.........'...1..| -00000010 17 00 1f 6c d5 91 ae 7c 77 87 98 05 67 9a ea ea |...l...|w...g...| -00000020 6c 79 28 da 2c 91 6d a0 c6 9a e9 f3 85 a0 7f 7d |ly(.,.m........}| -00000030 ae 89 ac 0d 01 7f d8 34 dd fb ba c3 d8 ba ff 9b |.......4........| -00000040 75 dc d6 5e 8a fa ad 9c ea fa 15 63 55 85 98 26 |u..^.......cU..&| -00000050 65 7a 19 17 c4 99 98 85 83 c4 06 39 30 d5 63 51 |ez.........90.cQ| -00000060 ff 22 e8 cd 55 6e fc 88 5e d5 54 24 79 52 7e b0 |."..Un..^.T$yR~.| -00000070 71 e4 e6 cb a6 06 24 14 1a c2 a8 52 85 e9 fc e4 |q.....$....R....| -00000080 66 47 9c 9c d1 f3 56 11 47 16 4b 7c a5 f1 81 1e |fG....V.G.K|....| -00000090 00 78 98 8f 70 ae 47 6d 45 3b c4 af fc 88 bd 88 |.x..p.GmE;......| -000000a0 7b cc 8a 78 86 ff 86 25 2d 21 28 f2 c5 d7 4b 61 |{..x...%-!(...Ka| -000000b0 c0 ea 67 38 4c d0 d6 6f fc a0 69 62 98 6f ac 29 |..g8L..o..ib.o.)| -000000c0 29 13 34 7a f0 2d 1b 7e 52 42 6f f1 64 ed 7f 47 |).4z.-.~RBo.d..G| -000000d0 69 82 9b 9d 19 7b 3a c5 54 51 c8 8f 4c 9e 42 a7 |i....{:.TQ..L.B.| -000000e0 0f 9e 05 1d 4f 85 11 05 97 42 fa 24 37 1c 4e ec |....O....B.$7.N.| -000000f0 55 dc e1 4e f6 e2 dd c6 63 b0 dd 60 11 93 23 8a |U..N....c..`..#.| -00000100 eb 68 76 21 ec 19 cf 59 c8 78 80 f0 fa 39 6a 09 |.hv!...Y.x...9j.| -00000110 f8 7f 9d c0 e7 51 3d 75 17 e3 cf a5 bf 1c 10 |.....Q=u.......| +00000000 16 03 03 01 34 d8 7e 6c f6 7b d5 eb 3f 49 63 78 |....4.~l.{..?Icx| +00000010 28 92 1c 8b 67 f2 70 a7 ff e2 91 42 43 d8 90 4e |(...g.p....BC..N| +00000020 01 47 0a 12 bb 9d a2 9a e1 a2 d6 ee 5e 91 8c 4d |.G..........^..M| +00000030 86 8e 29 d4 e0 b3 67 0f c4 5e a9 02 c9 e3 8f f0 |..)...g..^......| +00000040 e6 ea 24 50 da 57 70 35 58 98 81 3e ff b8 8d ea |..$P.Wp5X..>....| +00000050 b3 e0 f0 a1 91 39 69 33 40 bc 0f 67 21 10 67 f4 |.....9i3@..g!.g.| +00000060 93 66 0c f2 66 aa fd a5 2c 8d 2b 38 31 30 b3 50 |.f..f...,.+810.P| +00000070 71 09 de ce 22 59 c3 96 5a 07 84 c0 1f 96 5c e3 |q..."Y..Z.....\.| +00000080 7e 6b c8 7e 3f a5 32 77 20 3c 7b 92 df bc 11 57 |~k.~?.2w <{....W| +00000090 86 e5 a1 03 78 9c 08 ea 49 bc a7 1b 6b fb 47 6d |....x...I...k.Gm| +000000a0 9a 86 14 fa cc 98 e6 9a f8 39 18 57 36 fb 1b ff |.........9.W6...| +000000b0 ae ce 1e 96 20 9d 16 be c6 00 45 51 2a 5a 7b 46 |.... .....EQ*Z{F| +000000c0 9c c9 c1 eb fb fc 37 52 8d b2 22 e3 58 6a d1 fe |......7R..".Xj..| +000000d0 71 55 18 4b ff 92 e1 16 62 29 cb fb d0 0d 94 22 |qU.K....b)....."| +000000e0 13 ee 8e bb 75 2e 1c ae 11 61 3d 37 69 0d 51 b0 |....u....a=7i.Q.| +000000f0 61 e3 7f 94 08 54 3a 49 68 94 b5 64 da ac a9 a4 |a....T:Ih..d....| +00000100 e2 3f 65 ad d7 42 8e 0b 70 5f 4f 6d 6e 0c 27 51 |.?e..B..p_Omn.'Q| +00000110 5a 48 57 71 6e 9b 58 e0 6e 05 40 48 a8 20 36 98 |ZHWqn.X.n.@H. 6.| +00000120 f8 71 a3 ef 2d db 8c ae fa a5 14 d8 1f ff ad 7b |.q..-..........{| +00000130 2a 15 0d fb 3d e8 1b fe 48 |*...=...H| >>> Flow 8 (server to client) -00000000 16 03 03 00 85 14 4e 8e de d0 5b 59 2d f6 a3 b0 |......N...[Y-...| -00000010 c0 ff 4a ff 8b cf af 2f 09 f1 ee 03 0f b9 70 5e |..J..../......p^| -00000020 1b e4 ef b4 3e e7 c1 43 fb ea a8 68 4c 66 0a 55 |....>..C...hLf.U| -00000030 e8 51 a6 30 bb e3 f5 0e df 11 f2 e0 51 94 14 f6 |.Q.0........Q...| -00000040 1e c6 e8 9d 10 a2 20 9f f2 f6 1e f0 3c f3 ba ff |...... .....<...| -00000050 65 d1 f4 df 9e e6 18 9f a1 a5 9c 5f 4b 4f 20 98 |e.........._KO .| -00000060 4a f6 0b 95 da 01 1f ea c0 c4 39 39 8b fd 19 40 |J.........99...@| -00000070 8d 14 da 45 fd 51 3d a7 36 23 a0 b2 bb cb 81 6b |...E.Q=.6#.....k| -00000080 79 0a 02 71 50 84 ac d6 7b ad 16 03 03 02 69 b8 |y..qP...{.....i.| -00000090 a9 6c 87 d7 23 6b c6 1a 4c 08 dd fa 58 e8 e8 d5 |.l..#k..L...X...| -000000a0 44 16 3b de 77 60 33 2a 47 a5 3c e0 cb c3 1a 38 |D.;.w`3*G.<....8| -000000b0 1d 1f 69 8e 33 a3 ba ac 55 b5 77 9b e1 fc a4 21 |..i.3...U.w....!| -000000c0 99 90 01 5e 99 36 a3 cf 74 b4 1f 96 b7 96 1e 4b |...^.6..t......K| -000000d0 cf 0b 92 5f 6b 1f 1c b0 70 80 2e 87 57 ef 52 b0 |..._k...p...W.R.| -000000e0 2b 7d 66 06 cb a1 78 a7 5a e2 af 4c fc a4 8b 99 |+}f...x.Z..L....| -000000f0 af 6c 6d 0e 07 7e da 11 5a b7 89 af 3c ce 1e 22 |.lm..~..Z...<.."| -00000100 1f 7d 97 d5 d4 78 09 c4 e7 fb 33 bf 36 ee 6e 5a |.}...x....3.6.nZ| -00000110 af f0 5b 0f 00 eb cc 3d 76 35 41 98 4c 65 81 34 |..[....=v5A.Le.4| -00000120 74 d9 d7 ba 04 fc c8 c6 c9 ca 4b b0 8e b1 7e 87 |t.........K...~.| -00000130 9d 69 2e d5 68 54 96 48 37 42 ae ff 18 d0 08 b2 |.i..hT.H7B......| -00000140 dc 26 1c c1 99 f1 c3 02 3f 48 51 a8 92 10 18 01 |.&......?HQ.....| -00000150 f3 3b 96 4b de 80 29 27 87 da f4 89 23 1b 49 b8 |.;.K..)'....#.I.| -00000160 5b f5 50 ec 99 b0 c3 48 e2 d3 fe fb a0 95 c3 c6 |[.P....H........| -00000170 83 fe d9 87 ef 0c cf 67 8f e7 52 3d 17 7d c0 ab |.......g..R=.}..| -00000180 02 1a 33 78 c8 d6 13 8b 8e 82 be 0d 5e d4 22 e8 |..3x........^.".| -00000190 63 c3 84 a9 05 12 d3 b7 e2 36 96 a2 22 0a 77 df |c........6..".w.| -000001a0 20 06 5c 0d 8b c1 d6 ac 73 b0 b2 a0 be db 59 17 | .\.....s.....Y.| -000001b0 05 60 68 b9 18 85 d5 73 9b c9 41 b9 c1 f2 02 47 |.`h....s..A....G| -000001c0 ca 95 c8 47 e2 de 04 75 08 d4 b7 a2 41 d7 e2 6b |...G...u....A..k| -000001d0 ad 8c ba c5 fc f8 b1 fe d3 23 c0 22 ec d0 2f a7 |.........#."../.| -000001e0 d9 ed 0e da 71 18 c0 d0 1f 40 8d eb 79 ea 5f aa |....q....@..y._.| -000001f0 07 4f 65 81 c1 9e ea 36 7f 0d 8b 07 8b 71 81 5a |.Oe....6.....q.Z| -00000200 0e cb d4 0f 98 c8 5c 69 d0 61 6e b5 ef 2a dd 5f |......\i.an..*._| -00000210 63 92 b4 3e 6e f4 b8 fc 45 bf 58 79 08 a4 95 6f |c..>n...E.Xy...o| -00000220 34 01 9b 8a 19 a5 e4 11 3f d4 97 47 66 e8 42 ef |4.......?..Gf.B.| -00000230 92 72 01 f4 6f 07 a4 35 81 83 ee 26 d0 96 cc de |.r..o..5...&....| -00000240 42 2a 65 64 cc a9 0c 39 31 d5 7c 2f 42 e5 ce 36 |B*ed...91.|/B..6| -00000250 0b bf b5 22 2a 4f 3c 56 27 29 cd fb 8e 9f 8f ab |..."*O...d...V*.h| +000001e0 45 68 13 da c6 eb 5d f2 7b 51 bd b4 8e 25 0d b7 |Eh....].{Q...%..| +000001f0 f0 03 dd 2b cd 93 7f 00 96 ca 75 c1 1b c7 d0 95 |...+......u.....| +00000200 0f 08 52 e0 d6 c9 2c b2 42 b3 0b 0c ed e1 01 e3 |..R...,.B.......| +00000210 7d ef b1 fb 80 76 c8 08 ec 9f c2 13 a5 04 05 fe |}....v..........| +00000220 33 c2 b7 2e 1a 2b 4a 74 f5 f5 92 ad e8 cf f7 76 |3....+Jt.......v| +00000230 3e 7c 69 4b 2d be 9b 08 3b 80 97 66 63 e5 df db |>|iK-...;..fc...| +00000240 1a a4 aa 8a bd 43 2a 65 44 6d f1 e6 60 92 cd 98 |.....C*eDm..`...| +00000250 a9 ac 81 de fb 22 06 f4 ca 90 4a 67 64 3f 25 ab |....."....Jgd?%.| +00000260 3c db 77 cb bc 32 55 bc 2d 48 4e 32 c7 48 d1 2f |<.w..2U.-HN2.H./| +00000270 bf 80 03 7e 27 92 8b 6a 90 35 ab 8e 93 dd 27 c7 |...~'..j.5....'.| +00000280 7d d6 a7 ea d8 1f 6a 43 57 34 d2 a9 7c c3 23 55 |}.....jCW4..|.#U| +00000290 62 5b 98 80 a1 ec 61 53 63 b9 a7 89 85 7e a8 0e |b[....aSc....~..| +000002a0 31 e9 9f 82 e9 1a b3 25 b8 d3 bf 4b f7 da 40 ce |1......%...K..@.| +000002b0 30 95 8f 41 75 9e 99 f5 3f fd 90 57 77 ee ad b7 |0..Au...?..Ww...| +000002c0 56 1e fd a6 d6 98 ae d3 a0 36 8a e0 19 a5 64 63 |V........6....dc| +000002d0 8f 08 d3 e6 2b c3 8a 29 90 8d e0 d7 1d 8b 84 6d |....+..).......m| +000002e0 a8 7a 0d 8b 6d 0e d5 fa bd c1 31 13 c7 39 61 f6 |.z..m.....1..9a.| +000002f0 e8 b3 fd 4d fe 49 a0 2c 16 03 03 00 bc 6d 99 1c |...M.I.,.....m..| +00000300 76 24 e6 f4 79 ac da e5 71 78 32 8d df a7 74 a4 |v$..y...qx2...t.| +00000310 e1 22 43 86 62 7a 99 34 9e c1 c7 82 82 f2 ad c0 |."C.bz.4........| +00000320 cb e5 54 c7 2d 3f bd 00 ba 4f 9f 6b 90 c2 2c bf |..T.-?...O.k..,.| +00000330 d5 d1 20 48 28 f0 bc 21 d4 1f 8d a9 89 82 ce 3d |.. H(..!.......=| +00000340 b2 52 bd 91 57 65 da 07 74 d9 56 b3 54 a7 2c 20 |.R..We..t.V.T., | +00000350 93 5e 79 59 d0 d3 33 95 a9 de f6 a4 48 37 11 10 |.^yY..3.....H7..| +00000360 a7 34 2a 2b 30 a5 24 03 5b d5 63 78 1f ad ca 70 |.4*+0.$.[.cx...p| +00000370 ff f9 22 ca bc 23 ac 4d eb 5a d7 de af 31 72 25 |.."..#.M.Z...1r%| +00000380 84 24 72 b7 b8 c0 a5 7a b6 7e a9 95 42 bb 5e 52 |.$r....z.~..B.^R| +00000390 6c 13 87 c2 b5 17 04 a8 0a 43 d0 b4 96 12 12 4b |l........C.....K| +000003a0 1e d1 0b ab a1 5d 1a bc 48 15 ec 88 e6 7b 57 aa |.....]..H....{W.| +000003b0 da 3b 7f 0b cc 11 93 8f ee 16 03 03 00 4a 35 4e |.;...........J5N| +000003c0 5f 82 88 e9 d5 24 cc 81 3c 0a cc 49 63 13 ea 0c |_....$..<..Ic...| +000003d0 e6 d7 a9 f2 7b 4f 7f d4 c1 d8 71 4e 1d e6 68 e6 |....{O....qN..h.| +000003e0 7e ba 73 f8 23 a5 af 1a 05 35 4c bf 88 8d 8a 90 |~.s.#....5L.....| +000003f0 09 26 34 1d b6 88 92 2d 60 92 52 2c cb 45 02 a4 |.&4....-`.R,.E..| +00000400 78 54 3d a3 44 d3 f9 46 16 03 03 00 14 58 29 f7 |xT=.D..F.....X).| +00000410 44 f4 a0 9f 65 d8 47 1a 01 7e 1b 95 3b 5f 1f 4a |D...e.G..~..;_.J| +00000420 12 |.| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 8a dc ce d1 c0 85 30 95 6c da 57 |....i......0.l.W| -00000010 23 05 39 c1 4c 20 08 25 a2 96 f1 55 a1 77 3b 42 |#.9.L .%...U.w;B| -00000020 9f 3d 69 9b 56 49 b4 94 8a 3c d5 85 43 f1 b4 4b |.=i.VI...<..C..K| -00000030 cd e0 67 95 83 34 90 89 81 f0 18 87 28 c0 42 88 |..g..4......(.B.| -00000040 b0 1c d1 cc 0a f0 bb 67 91 55 0b e4 ed 22 52 09 |.......g.U..."R.| -00000050 92 0b 56 ac d0 3f c9 41 05 8a 19 7d e7 9a d7 ff |..V..?.A...}....| -00000060 fa 85 f5 23 b0 98 a0 79 b1 8e 0f 90 0e c8 32 92 |...#...y......2.| -00000070 4b 6a 37 47 45 31 70 be 8b cd 7a 26 3a 3c 0b 63 |Kj7GE1p...z&:<.c| -00000080 a7 8c 00 2c 1d be eb 5c 1f 16 90 76 2b d7 82 5e |...,...\...v+..^| -00000090 31 93 40 7a e0 9a e0 4c 7d 2e e3 84 0f cb 06 7d |1.@z...L}......}| -000000a0 8d 76 41 ea 27 52 4a 77 e5 91 02 ab 11 cc 8c f0 |.vA.'RJw........| -000000b0 fe 8e ee b2 f1 ba 1e ab 0d 5c e2 2d da d5 8d f9 |.........\.-....| -000000c0 7c 22 32 e9 50 1d 88 db af c0 82 51 e0 31 14 71 ||"2.P......Q.1.q| -000000d0 ad c9 05 5d 8e 2b 75 4b 9e 74 b0 3a a9 e4 7c 82 |...].+uK.t.:..|.| -000000e0 ac 75 39 31 0a dc dc 0a 5c f4 ee 55 f2 09 c2 d2 |.u91....\..U....| -000000f0 81 c8 70 2e 8f 37 6b 90 79 5c 18 6e 38 21 c6 00 |..p..7k.y\.n8!..| -00000100 08 be ad 21 e9 40 b6 54 06 f0 61 f9 2c 71 25 0e |...!.@.T..a.,q%.| -00000110 13 6c 66 ef b6 a9 61 d0 d0 42 56 58 32 3c 9c 5a |.lf...a..BVX2<.Z| -00000120 ee 13 1d 42 8b 94 41 9c d1 2e c9 ac d4 ed 0f 04 |...B..A.........| -00000130 1c 6f 5c 30 80 12 37 c6 43 07 7e 03 50 86 24 84 |.o\0..7.C.~.P.$.| -00000140 34 2a 70 82 65 67 35 cd 5e 7c 0e 49 30 35 d4 ee |4*p.eg5.^|.I05..| -00000150 43 b7 7a c3 88 30 e5 ba 98 7f 8d 9e 08 a2 8c bb |C.z..0..........| -00000160 48 44 c2 1a 8d 7b 41 de b6 68 ae d2 8a 64 9b 6b |HD...{A..h...d.k| -00000170 8a 47 88 04 49 05 8a 94 66 da d3 90 78 6d 81 64 |.G..I...f...xm.d| -00000180 4e 6b a5 6f d2 9d 1d 36 6f a2 a3 83 0c f5 69 10 |Nk.o...6o.....i.| -00000190 37 c8 b8 59 c7 b1 5b 91 fc e3 26 37 da 14 80 8f |7..Y..[...&7....| -000001a0 d4 1e 63 51 1d 77 85 67 af 7a 7d e4 5a 27 f9 3f |..cQ.w.g.z}.Z'.?| -000001b0 75 b0 9e 2a 1d 42 29 ac d4 29 c6 0d 2f ee 35 38 |u..*.B)..)../.58| -000001c0 38 91 a4 f1 60 1b d6 49 b2 eb c4 df b6 01 99 69 |8...`..I.......i| -000001d0 06 7c ca 2d aa 15 e8 c5 4f 48 5f 77 87 4b fd 41 |.|.-....OH_w.K.A| -000001e0 cf aa 7d 96 b9 12 ee b7 b3 a2 86 5e 4f 79 08 a1 |..}........^Oy..| -000001f0 00 43 12 93 92 99 07 44 23 48 78 46 c8 fc 4a 96 |.C.....D#HxF..J.| -00000200 88 72 45 2a f4 ff 92 41 7b e5 a0 74 93 ff b8 f6 |.rE*...A{..t....| -00000210 3e e0 6a 3b 3b 12 68 50 89 d1 d3 22 e0 a1 3f ef |>.j;;.hP..."..?.| -00000220 da 18 15 5b c2 48 0e 78 d0 af ae d7 81 af 23 16 |...[.H.x......#.| -00000230 ab 71 07 9d 26 b2 8b 34 7e b2 1a 1e f4 fb 02 9a |.q..&..4~.......| -00000240 f4 15 78 a9 d2 19 94 bb 9f b0 ba 2a 21 20 dd 87 |..x........*! ..| -00000250 57 73 e7 01 08 bc 38 ce 2d 9e dc 3f f7 c4 75 aa |Ws....8.-..?..u.| -00000260 00 9d 28 43 e5 de aa 82 fb e5 ca 87 4e 6c 16 03 |..(C........Nl..| -00000270 03 00 35 e0 37 f9 95 cd 96 f9 ba 36 12 6b 35 c5 |..5.7......6.k5.| -00000280 02 9d 71 8a e5 07 d6 1c 77 6a 86 17 d0 01 9b 79 |..q.....wj.....y| -00000290 74 6b 14 27 33 2f 6d c2 af cb dd 47 71 b3 73 4d |tk.'3/m....Gq.sM| -000002a0 7f 42 3e 7f 86 6e 63 ed 16 03 03 00 98 7f ba 78 |.B>..nc........x| -000002b0 bf a3 d4 02 cb 19 0d 1f 48 bf 4d 9f d0 37 3a c9 |........H.M..7:.| -000002c0 c1 76 6e fb 9a 69 63 0a a1 76 13 2d ea 52 38 18 |.vn..ic..v.-.R8.| -000002d0 71 89 9a f5 02 2e 44 94 72 6d 08 e1 89 9a e1 4c |q.....D.rm.....L| -000002e0 ee 2f 15 9c 0d b6 67 1e 0c 17 b0 e9 03 7d 66 1c |./....g......}f.| -000002f0 28 6b 57 6d c8 49 5d ef ca 4c 51 59 ae 17 55 97 |(kWm.I]..LQY..U.| -00000300 54 f1 f5 64 19 ec 36 27 96 33 0e fd 65 42 ac 50 |T..d..6'.3..eB.P| -00000310 bb cf f9 da fe 98 3d 83 79 a0 24 0d 9f 91 5c b0 |......=.y.$...\.| -00000320 5c c5 04 b4 90 53 c3 8b b5 29 c5 73 7f 04 c6 55 |\....S...).s...U| -00000330 93 4a 08 67 8f f7 a8 ba a8 e2 62 09 85 d3 47 b9 |.J.g......b...G.| -00000340 27 bd 6c 81 95 14 03 03 00 11 88 9b 21 1e 06 0a |'.l.........!...| -00000350 fa 8a 9e 4e d9 7a b3 a5 45 7a 96 16 03 03 00 20 |...N.z..Ez..... | -00000360 6f a0 f0 cf 0b 2b c2 d1 36 d8 64 2b 72 86 7b ab |o....+..6.d+r.{.| -00000370 c7 86 5d c3 67 ec d6 c0 32 4d b8 1f fa d9 3a af |..].g...2M....:.| +00000000 16 03 03 02 69 ef e7 da 35 77 b6 d6 09 a1 71 43 |....i...5w....qC| +00000010 1c 2b 72 d6 65 ea b4 38 e4 13 c1 85 c3 36 bb f4 |.+r.e..8.....6..| +00000020 ef 1a b8 94 de 11 22 6e b8 28 14 05 88 2a 5d 7a |......"n.(...*]z| +00000030 7c 0a 00 ac 74 ce 4f f8 b3 94 5d 5c a1 aa 3e 20 ||...t.O...]\..> | +00000040 ee 0b e3 50 3d e7 4f 4d ad 5c 9e 6e 8e 75 26 b4 |...P=.OM.\.n.u&.| +00000050 80 e1 85 3f ae 76 6f 95 6e f0 79 98 3d 86 17 9c |...?.vo.n.y.=...| +00000060 e9 d6 35 1d f5 15 ea c5 29 67 15 9d 03 4b 41 9d |..5.....)g...KA.| +00000070 25 b3 ab 3a b0 12 d1 ff fc 9e 25 af ff 8a c8 1c |%..:......%.....| +00000080 4b 4e f0 10 9d d3 98 6e 66 0a 13 82 b9 04 d7 39 |KN.....nf......9| +00000090 b2 2c c5 f9 cf be 4b 8b 8a 28 e9 24 db c8 fe d6 |.,....K..(.$....| +000000a0 a1 b1 3c 9e 19 92 0b 5d 2e c8 5f 56 35 dc 16 46 |..<....].._V5..F| +000000b0 7b a1 d2 43 d9 ee 3f a7 74 c1 4c ed 2a 84 4a ad |{..C..?.t.L.*.J.| +000000c0 76 a2 bc 90 8d 19 06 11 1a 6d b8 e0 3a 8e 0d 33 |v........m..:..3| +000000d0 f2 ad 06 d7 e5 a3 16 8c 14 07 4c 84 8a 47 13 c1 |..........L..G..| +000000e0 b1 cb 81 8b d7 5b fb 04 2b da 3c 7f d1 0f 2b 8b |.....[..+.<...+.| +000000f0 23 ad f5 f1 09 82 24 80 5c bc f7 68 69 c0 90 5f |#.....$.\..hi.._| +00000100 fa 96 b4 9d 51 0e 96 1e 06 2a d1 98 5d 96 95 68 |....Q....*..]..h| +00000110 de df 40 f9 f6 b1 f2 ef a7 c4 0c 05 ee b3 63 8d |..@...........c.| +00000120 3a 1e a2 d8 34 2a b2 99 c3 17 03 60 18 4f 43 21 |:...4*.....`.OC!| +00000130 99 4f 81 c1 11 8e a4 45 79 d8 fa fc b2 9a f8 d0 |.O.....Ey.......| +00000140 95 10 79 38 45 1b 82 42 f0 bb 75 27 6b a2 53 d3 |..y8E..B..u'k.S.| +00000150 e6 dd 2d 43 f5 80 fd 9a 59 ec 07 42 ee b0 9d bd |..-C....Y..B....| +00000160 33 dd 58 c8 57 e8 16 de a4 21 c9 92 51 d2 e5 8b |3.X.W....!..Q...| +00000170 48 f5 cb a8 3a d8 f6 a3 b2 00 90 9e f0 e0 ca c7 |H...:...........| +00000180 fe 79 70 f7 8e 5c 4b 3c 86 c8 cc ca b1 b6 05 e2 |.yp..\K<........| +00000190 90 66 db 85 fc 7c 87 6f e0 44 ed 2a c9 66 b7 de |.f...|.o.D.*.f..| +000001a0 c5 f0 d2 80 dd f2 c2 26 5b 84 cf b0 c4 78 7e 65 |.......&[....x~e| +000001b0 66 d9 d8 c5 fe 97 b9 27 6e 55 11 c0 0b 3e e2 c9 |f......'nU...>..| +000001c0 ce 4d dd 27 28 6f 62 45 70 b3 e4 0c 18 31 f1 b2 |.M.'(obEp....1..| +000001d0 33 8f 7d 34 7c f6 f3 50 d9 a9 6b ec a7 cf c2 7b |3.}4|..P..k....{| +000001e0 36 21 d7 76 68 c1 0e 90 8d af 2e c5 d5 26 c7 c1 |6!.vh........&..| +000001f0 0b 1c 43 85 a6 43 3e 96 67 46 2d 1e 0a c8 90 99 |..C..C>.gF-.....| +00000200 0f 71 cc 60 49 68 2c df 17 68 e4 fa 79 05 50 ac |.q.`Ih,..h..y.P.| +00000210 16 d0 26 1f 7e 58 a2 dc 73 e9 05 8d 92 f6 8c 56 |..&.~X..s......V| +00000220 db 08 0a b7 99 64 f7 5b d0 5f f3 88 f5 02 f5 d0 |.....d.[._......| +00000230 66 55 e3 db f4 d1 c9 d3 c1 f4 ab 8c 5c 39 fd 64 |fU..........\9.d| +00000240 ec cd ab 63 da 7b 3e 64 1a b4 c3 d9 79 bd 92 e3 |...c.{>d....y...| +00000250 97 68 a4 83 b5 f1 fa f5 05 04 84 39 e9 82 a6 84 |.h.........9....| +00000260 e5 a0 6f a2 6d ea 6b ab 4c f8 a5 87 9c 9c 16 03 |..o.m.k.L.......| +00000270 03 00 35 08 0b 50 f9 90 d3 e9 58 e5 5b df a1 99 |..5..P....X.[...| +00000280 89 ea 0b 1a f1 4d e3 fd a6 79 2c 61 ac 6f da 7c |.....M...y,a.o.|| +00000290 2a 78 e1 38 05 35 2e 8b db eb 25 fd eb 2f d7 a3 |*x.8.5....%../..| +000002a0 27 9d 27 f2 b3 ff 20 8a 16 03 03 00 98 95 42 7e |'.'... .......B~| +000002b0 d5 86 40 42 dc 93 fe 80 ef 70 cc fb 2f b1 51 bd |..@B.....p../.Q.| +000002c0 ca 5f 1e 0d a0 3f c6 e0 c9 69 0e d4 dc 18 25 52 |._...?...i....%R| +000002d0 5c c2 8c 37 f6 a8 e6 4d 48 27 81 4d 7a f3 49 5c |\..7...MH'.Mz.I\| +000002e0 92 92 68 a9 e0 dc d6 c5 b5 ea 99 5c 51 df 93 a1 |..h........\Q...| +000002f0 36 2d 65 a8 cb ca 72 76 53 92 7d c7 81 5f 19 2c |6-e...rvS.}.._.,| +00000300 3e 83 29 16 41 65 4f 81 d7 3f 5c 15 f0 36 d9 75 |>.).AeO..?\..6.u| +00000310 a7 c8 52 6f 5b b6 98 46 5e 39 31 83 1c 99 3f f9 |..Ro[..F^91...?.| +00000320 9e 28 d7 94 ae a7 b4 f7 c9 ce 5b 74 2f 88 9e fd |.(........[t/...| +00000330 3c 1c 1e eb f4 b3 39 65 39 07 14 8e 3e 95 87 b2 |<.....9e9...>...| +00000340 b8 4c e8 7d 3b 14 03 03 00 11 cc eb 21 2a 7c 9a |.L.};.......!*|.| +00000350 5c 35 9f 35 e3 09 dd f8 7a 4f 43 16 03 03 00 20 |\5.5....zOC.... | +00000360 0b ff 00 c0 96 43 18 d9 9d ad 51 55 44 40 11 2f |.....C....QUD@./| +00000370 cd 1c bd ae ea 0a c9 eb de 57 95 c2 81 63 79 4c |.........W...cyL| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 b4 79 7e 62 ea ea f7 37 1d a4 65 |......y~b...7..e| -00000010 9d 02 95 b8 4a 6c 16 03 03 00 20 6a 45 d1 d0 ff |....Jl.... jE...| -00000020 fa 9f 6a ea d5 0d 27 b6 e7 15 8b e8 5b f9 3c d0 |..j...'.....[.<.| -00000030 32 ff 81 24 9a de 1c 31 6a 48 f8 17 03 03 00 19 |2..$...1jH......| -00000040 a9 07 ab fb 37 2f 88 0c 93 4a 0c 34 08 26 39 8c |....7/...J.4.&9.| -00000050 22 00 1b 36 3c 6d 0c 49 61 16 03 03 00 14 bb 63 |"..6>> Flow 11 (client to server) -00000000 16 03 03 01 1a a4 4c dc 47 09 04 ab bb ca 49 f2 |......L.G.....I.| -00000010 63 36 35 fb e3 3f ad ae 82 2a 9b 87 cc 0c 2e ea |c65..?...*......| -00000020 18 af ad e9 ea 7a c8 45 de c6 9b 0e e0 32 26 95 |.....z.E.....2&.| -00000030 ba e3 57 9e 27 ce ff 36 43 a3 bd 79 47 6c 02 86 |..W.'..6C..yGl..| -00000040 81 44 ac b3 c6 21 d8 fa 8c 69 43 b7 66 70 ea 24 |.D...!...iC.fp.$| -00000050 12 1b ac 44 d2 49 e3 5a d1 0e 50 76 46 4f 58 51 |...D.I.Z..PvFOXQ| -00000060 21 4c f8 20 63 60 c0 20 3a 12 e5 0b 86 e3 03 2c |!L. c`. :......,| -00000070 e1 fc 63 e4 44 d4 67 95 aa af 22 3d 40 7b 4e 12 |..c.D.g..."=@{N.| -00000080 98 7d 05 00 57 50 d5 3a d7 af dd 96 0f ac 77 63 |.}..WP.:......wc| -00000090 f8 1c b0 9c d0 96 9f 20 a1 48 55 aa dc 69 fb b7 |....... .HU..i..| -000000a0 67 58 ff 27 de 22 ea 66 48 32 56 1f ef 12 3f 44 |gX.'.".fH2V...?D| -000000b0 38 af ae 4b c2 16 bb c8 f1 fe 13 d7 05 66 de 08 |8..K.........f..| -000000c0 f3 4d 5c a6 e1 2d 0d c3 ce 50 7b 01 40 49 0f 83 |.M\..-...P{.@I..| -000000d0 97 c0 37 a2 6c 2b 64 a9 40 0e e1 7b f4 6e e1 cc |..7.l+d.@..{.n..| -000000e0 1a 5f 0b c5 69 dc dc db 0e a2 22 7b cf ca 73 81 |._..i....."{..s.| -000000f0 fc 47 47 c7 76 18 8e ae 55 6c fe 5e 5e 33 84 9c |.GG.v...Ul.^^3..| -00000100 4c 1b f8 21 29 3c 47 1b c8 01 38 7d c2 50 45 1c |L..!).1....#..tE{..| +00000120 d8 c8 c0 8b 00 72 ee d8 a9 64 b8 1b 48 77 98 b9 |.....r...d..Hw..| +00000130 20 61 b8 23 17 b5 65 7c fb | a.#..e|.| >>> Flow 12 (server to client) -00000000 16 03 03 00 85 bb 34 66 c0 a3 8c 2b 2c fe fe 82 |......4f...+,...| -00000010 53 a1 07 1f 06 db 41 94 ac 21 f2 c4 23 0e b6 48 |S.....A..!..#..H| -00000020 4d 16 97 2a 79 dd 95 4c 93 7f e4 8c 94 90 d4 02 |M..*y..L........| -00000030 3c 44 b4 80 80 7b 45 84 53 3f 6b 9f f6 b6 d3 0c |.c....>TP..alX | -00000200 da a8 5a f7 46 9d a3 57 a1 60 72 59 82 dd f7 08 |..Z.F..W.`rY....| -00000210 9e 48 16 8d b1 c0 f4 d2 e0 4e 5d 3c bf 23 88 0f |.H.......N]<.#..| -00000220 99 90 b0 a9 7e df 0b f5 1a 31 9e 59 e1 05 43 4e |....~....1.Y..CN| -00000230 4f d9 a5 b1 00 2e f2 c8 10 2c 73 ec c4 62 b8 c3 |O........,s..b..| -00000240 59 53 ce 38 37 9d c3 f6 77 36 34 f2 07 a6 21 1f |YS.87...w64...!.| -00000250 62 56 08 d3 ed ae 51 05 4d ed ef 7e 77 c5 7d ae |bV....Q.M..~w.}.| -00000260 b6 aa 74 e9 9a df 5d 89 c2 9f 07 75 a0 c2 35 2d |..t...]....u..5-| -00000270 cc 13 c5 a9 17 85 79 b6 45 0c 82 56 0d 19 9e bc |......y.E..V....| -00000280 e7 1a a6 cc 20 6f f9 7c 29 54 2f 5a 92 1f c0 8b |.... o.|)T/Z....| -00000290 9c a7 a3 85 43 f2 4c e7 c5 e3 af 6e 40 f4 14 d4 |....C.L....n@...| -000002a0 b8 26 5f ac d7 44 16 6d 40 d5 80 c5 49 df 8d fe |.&_..D.m@...I...| -000002b0 06 1c 7c 19 49 94 50 6f e8 8c e0 59 80 9a a0 0e |..|.I.Po...Y....| -000002c0 50 3f 03 de c9 30 88 15 91 83 4e a8 df c3 65 75 |P?...0....N...eu| -000002d0 cd 30 3e 7d 32 4a d9 ff 72 1e 1d 90 50 f3 67 8a |.0>}2J..r...P.g.| -000002e0 6a 94 c3 92 9a d4 0b 20 7e 61 98 6e db d0 71 4a |j...... ~a.n..qJ| -000002f0 8b 43 82 7e 76 e6 93 f7 16 03 03 00 bc e6 e6 85 |.C.~v...........| -00000300 a8 2c 74 47 10 a3 27 26 f7 46 fb da fa 6a 93 2c |.,tG..'&.F...j.,| -00000310 b1 14 b2 90 d3 4e 94 42 c4 37 6d 4d 43 73 b4 a7 |.....N.B.7mMCs..| -00000320 17 c1 3c 62 5d e4 c4 04 7c f7 13 39 9f a8 3f 05 |....d....| -00000390 e5 f8 f3 75 54 65 f4 6f e9 c8 eb a2 6c 06 98 fd |...uTe.o....l...| -000003a0 e9 bb a2 93 ab ee 0b fa c7 b4 fa e1 91 34 a9 a7 |.............4..| -000003b0 b9 14 16 25 32 88 09 3e b1 16 03 03 00 14 d0 c0 |...%2..>........| -000003c0 54 b2 37 35 9b cf 51 71 28 b2 d6 86 05 16 ad a0 |T.75..Qq(.......| -000003d0 18 e7 |..| +00000000 16 03 03 00 85 93 93 97 db ec 52 74 ce 78 ca e6 |..........Rt.x..| +00000010 95 19 ac 68 2c 81 ad 6b c3 6d d5 f7 84 a1 00 d0 |...h,..k.m......| +00000020 15 4c ae 2d 10 6a 07 d3 82 af af f8 d9 5d 9d 65 |.L.-.j.......].e| +00000030 8d c9 1e 8c 61 3e b3 67 71 89 41 7e 94 1e 4a 27 |....a>.gq.A~..J'| +00000040 73 53 83 d4 70 44 9a 4f 8d e7 62 af 9b 71 9e 83 |sS..pD.O..b..q..| +00000050 72 9a a1 e2 03 47 5f c3 11 4f 56 b9 6f 02 b5 b8 |r....G_..OV.o...| +00000060 8b 4a cb 99 ed 62 58 45 2d 0f f1 25 ce e9 de 7d |.J...bXE-..%...}| +00000070 3f 17 a8 35 d5 73 06 6e d6 bc 77 2a 82 27 d7 92 |?..5.s.n..w*.'..| +00000080 91 67 68 07 52 4b ed a0 3c 95 16 03 03 02 69 11 |.gh.RK..<.....i.| +00000090 73 93 d5 ad 00 17 11 3b 83 81 68 6d 3a 8a 02 1b |s......;..hm:...| +000000a0 90 df 84 f6 2b 4a b8 98 cf 50 0d dd 29 22 9d 58 |....+J...P..)".X| +000000b0 ea 7b 2c 30 2d e7 e2 d1 ae ad 00 9e 01 f6 ef 96 |.{,0-...........| +000000c0 ae a4 48 58 29 63 1d 2c 19 f3 c2 49 6f cf c9 7b |..HX)c.,...Io..{| +000000d0 e3 ca 5c e7 30 a0 b5 72 a9 3d 61 a2 0f 96 e4 d6 |..\.0..r.=a.....| +000000e0 8f 93 66 f1 de 24 88 14 9f 8b 14 9a b5 94 f7 70 |..f..$.........p| +000000f0 79 e4 94 68 b7 e0 f1 8e d0 1b 56 da d0 ce 90 b2 |y..h......V.....| +00000100 13 b3 4b b5 20 99 77 4a a4 83 47 4e 1b 1f db 35 |..K. .wJ..GN...5| +00000110 96 16 f0 d8 2b 7e 18 bf 0c b7 a3 da 44 fe 4c 96 |....+~......D.L.| +00000120 86 06 52 81 f9 a1 f4 ab 43 6d a3 fd 50 f6 83 08 |..R.....Cm..P...| +00000130 ba b5 d5 15 55 16 aa 84 95 77 1d 9e cd d6 53 d0 |....U....w....S.| +00000140 d3 c7 1c 9a 12 4d 8d 7a b5 0b 02 34 3f cf b5 0f |.....M.z...4?...| +00000150 98 56 cc 6e 15 ef 60 88 e0 71 2e 47 46 ce 19 11 |.V.n..`..q.GF...| +00000160 81 21 fe c6 80 86 d7 be d9 a7 6f a1 8c 8d ff ba |.!........o.....| +00000170 fb 8b 8b 8f 35 95 03 cb 10 e6 f5 71 18 d5 3c e0 |....5......q..<.| +00000180 60 e7 a2 47 36 41 a0 a3 c4 a3 c1 23 6c da 55 6a |`..G6A.....#l.Uj| +00000190 5f ef cd 58 e7 5d d3 cf 50 7b 3d b5 c6 7c 73 d9 |_..X.]..P{=..|s.| +000001a0 ce c3 ae 6a 46 4a 9a e6 10 57 53 b3 6c e5 ec 9d |...jFJ...WS.l...| +000001b0 f0 25 3c a4 a6 f0 42 1a 1e 8c 2b 40 79 e5 51 84 |.%<...B...+@y.Q.| +000001c0 79 6b c5 8a 3d 25 11 38 97 ca 15 11 e7 51 74 29 |yk..=%.8.....Qt)| +000001d0 66 9e 4d 4d 50 6a ec 1d 94 6b 4d c9 e9 a7 f8 4e |f.MMPj...kM....N| +000001e0 5b c3 06 74 ba 1d a1 79 3c 24 94 c9 3b b0 b1 16 |[..t...y<$..;...| +000001f0 fe 42 31 fe d0 4b e4 51 e6 06 63 89 2d 3b 56 6a |.B1..K.Q..c.-;Vj| +00000200 cf 89 4c 45 49 fd 10 58 9b 6b 4b 35 eb d8 c9 9d |..LEI..X.kK5....| +00000210 c0 31 b6 3e 33 da 7e 87 39 e3 c0 6a f8 7f bd 9a |.1.>3.~.9..j....| +00000220 26 4f 42 51 86 40 fb f7 fb cc 50 80 b6 0a 63 f4 |&OBQ.@....P...c.| +00000230 41 62 68 c0 b8 99 7d 8e ab e1 8a 15 92 f2 35 a4 |Abh...}.......5.| +00000240 cc 0e e7 9e 74 2d c1 b4 44 be 25 10 92 02 4f e3 |....t-..D.%...O.| +00000250 e7 ea c4 77 83 18 62 36 ba 9c 77 a6 d4 c1 6f 66 |...w..b6..w...of| +00000260 fc 07 4b 1a 00 98 a4 10 5e bc d5 93 07 e7 0c e3 |..K.....^.......| +00000270 34 05 32 23 c7 60 22 a8 52 fa 6e de 3f f9 c6 cc |4.2#.`".R.n.?...| +00000280 c2 54 08 d4 2a 98 39 20 09 f4 1d 8e d5 18 77 5a |.T..*.9 ......wZ| +00000290 f0 f4 08 a4 66 a7 8e fe f5 25 50 16 ca 4a 8d f0 |....f....%P..J..| +000002a0 b4 9f f1 37 e6 9b db 24 25 d0 a0 57 06 74 e2 14 |...7...$%..W.t..| +000002b0 46 51 e9 9c 03 f0 e0 16 17 d0 c9 54 54 29 e6 04 |FQ.........TT)..| +000002c0 9a c3 47 93 69 78 1a de ca f1 d4 b1 52 ff c0 5c |..G.ix......R..\| +000002d0 9f 5f 16 a9 35 01 f9 18 47 7b ee 06 f4 f3 3a 1d |._..5...G{....:.| +000002e0 94 b9 d5 2c 29 a0 80 85 b0 31 55 37 63 bc a6 e6 |...,)....1U7c...| +000002f0 67 66 21 5f eb 1c 17 15 16 03 03 00 bc 93 4b d6 |gf!_..........K.| +00000300 07 b0 12 ca 98 9f 52 b8 14 c3 6e d4 3b f2 74 e4 |......R...n.;.t.| +00000310 f5 6f 51 40 04 cd 1a 5f 69 fb 3d 68 2b 4e 09 df |.oQ@..._i.=h+N..| +00000320 c8 c9 6f c2 87 ae b6 f9 14 6a 41 fa 59 08 0b b0 |..o......jA.Y...| +00000330 d9 0b d0 61 fd 64 c6 52 3e 40 f2 96 75 b0 82 7a |...a.d.R>@..u..z| +00000340 8e 68 11 d2 bc 22 a0 bc 30 d8 a6 1a 88 26 00 d5 |.h..."..0....&..| +00000350 b5 26 49 c2 5d f3 19 c5 c0 9d 75 c3 f4 3e 95 85 |.&I.].....u..>..| +00000360 d0 8b de 31 79 b5 5c 27 6e 99 ab 50 fe ef 3a 07 |...1y.\'n..P..:.| +00000370 a0 a9 ce b7 4b 29 6b 93 42 6d db 34 6b 14 03 a9 |....K)k.Bm.4k...| +00000380 a8 1f c2 57 65 64 c3 95 ff 2a f8 39 de c3 36 f4 |...Wed...*.9..6.| +00000390 dd 77 b0 cf 86 be c4 9c 1d d5 ea 88 3c 8c ed 81 |.w..........<...| +000003a0 51 fc a9 80 78 bc 59 7d d1 e4 48 d5 d6 07 88 e1 |Q...x.Y}..H.....| +000003b0 d7 85 80 81 3a 35 9c 57 21 16 03 03 00 14 d9 b1 |....:5.W!.......| +000003c0 fb 95 82 67 c4 35 92 cd 47 cb 7b 0f 63 1a e0 32 |...g.5..G.{.c..2| +000003d0 43 75 |Cu| >>> Flow 13 (client to server) -00000000 16 03 03 00 35 e8 18 a5 be 6e 3b 37 5b d3 81 d3 |....5....n;7[...| -00000010 ad 0b 90 2e e0 df 2b 7f c4 ec 54 58 ef 85 e3 13 |......+...TX....| -00000020 41 07 50 d1 06 9b 3e a3 71 30 bf 7d 0c 7a bd 1e |A.P...>.q0.}.z..| -00000030 b6 e9 1e 10 0d 18 e3 b3 1c 38 14 03 03 00 11 bf |.........8......| -00000040 b3 65 ae 3b e6 c2 ad 30 83 75 65 c0 2b 0d 4b 11 |.e.;...0.ue.+.K.| -00000050 16 03 03 00 20 c6 cb f8 69 c3 bc 36 74 ff 8a 1f |.... ...i..6t...| -00000060 02 ef 32 37 fe 4f 14 51 d2 11 6a 98 05 4c 8c f6 |..27.O.Q..j..L..| -00000070 75 05 f9 39 2c |u..9,| +00000000 16 03 03 00 35 36 32 d0 64 c8 ba 33 1d 4f 31 73 |....562.d..3.O1s| +00000010 68 35 f2 76 0c b1 52 12 f5 4b 8a ea 74 0a 7f c2 |h5.v..R..K..t...| +00000020 a4 90 75 1f 24 0a 76 77 1f 01 15 9d 59 fa 16 56 |..u.$.vw....Y..V| +00000030 cc fd f9 08 74 76 31 cc f4 4c 14 03 03 00 11 c0 |....tv1..L......| +00000040 12 9b 35 78 94 a3 4e c3 b2 30 aa c7 fa 44 20 e6 |..5x..N..0...D .| +00000050 16 03 03 00 20 c6 a5 79 48 7b c3 2b 2d 6a 73 0a |.... ..yH{.+-js.| +00000060 83 a9 2b a7 ba 90 ea 6f b5 c2 c1 13 d7 7a 86 37 |..+....o.....z.7| +00000070 5a 24 8e f9 b3 |Z$...| >>> Flow 14 (server to client) -00000000 14 03 03 00 11 a0 fa 14 67 3f 54 1b 61 89 ed db |........g?T.a...| -00000010 9c 66 9f 49 77 2d 16 03 03 00 20 ca 47 f0 57 8c |.f.Iw-.... .G.W.| -00000020 3e 52 e6 e2 6c 01 cb 16 05 68 5e 19 12 ca 80 48 |>R..l....h^....H| -00000030 dc e9 ed 41 33 08 01 ef 6e b0 a3 17 03 03 00 19 |...A3...n.......| -00000040 d9 c8 68 e8 27 3d cf c0 33 71 55 a9 6a b4 6d a5 |..h.'=..3qU.j.m.| -00000050 da 8d bb 34 94 4f b1 c6 22 |...4.O.."| +00000000 14 03 03 00 11 c4 0e 59 d8 5e f6 5b 1d e6 20 7b |.......Y.^.[.. {| +00000010 45 4f 89 cd 2b a9 16 03 03 00 20 58 ff 80 6c f2 |EO..+..... X..l.| +00000020 fd 94 e7 66 b3 6d e3 37 57 8a 8c 35 98 4e bb c3 |...f.m.7W..5.N..| +00000030 42 87 32 b7 3b 6f ee 0f f1 7d 08 17 03 03 00 19 |B.2.;o...}......| +00000040 8a f6 02 17 4e 8a 1e 2b db 44 24 d4 aa c6 d4 af |....N..+.D$.....| +00000050 ef 5a a3 17 ba 77 f4 54 6e |.Z...w.Tn| >>> Flow 15 (client to server) -00000000 15 03 03 00 12 15 66 43 1e 60 21 d1 f6 94 34 3e |......fC.`!...4>| -00000010 ee 90 fc 87 45 2a f5 |....E*.| +00000000 15 03 03 00 12 84 3f 11 0b 00 bd 12 5e be 74 4d |......?.....^.tM| +00000010 04 e4 44 b2 01 73 66 |..D..sf| diff --git a/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected b/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected index 7698b6791da..62b6831a47b 100644 --- a/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected +++ b/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 e3 fe 9a 75 3b |....]...Y.....u;| -00000010 82 ac ff 66 ee c2 e9 75 d9 29 cc 89 6d e0 27 19 |...f...u.)..m.'.| -00000020 62 07 0b 0b c0 49 df 17 26 af 63 20 2a 95 69 54 |b....I..&.c *.iT| -00000030 3c 5d d9 67 05 4c 45 77 d0 d9 46 29 ed 25 fd 7d |<].g.LEw..F).%.}| -00000040 b4 ef 39 d2 ee 3b a3 88 85 c5 78 9a cc a8 00 00 |..9..;....x.....| +00000000 16 03 03 00 5d 02 00 00 59 03 03 a1 1a ae 12 c9 |....]...Y.......| +00000010 55 34 c9 23 81 cb 4f b0 d8 35 97 8e d5 b7 ac 67 |U4.#..O..5.....g| +00000020 e1 9c fd ec 35 61 48 7b d5 c8 8b 20 e1 e9 61 af |....5aH{... ..a.| +00000030 0b 5c 69 7b cb f9 7a ee 73 31 20 07 c3 b9 27 47 |.\i{..z.s1 ...'G| +00000040 07 e1 c0 34 7c c5 8f 31 ac 9d cd 8c cc a8 00 00 |...4|..1........| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,189 +62,191 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 ca 74 42 |............ .tB| -000002d0 03 67 f2 31 ac 68 dd 2c db 23 7d 2c 84 df e9 50 |.g.1.h.,.#},...P| -000002e0 ff ef d4 a1 fa a4 5b 0b 0b 73 20 b7 0e 08 04 00 |......[..s .....| -000002f0 80 41 60 3d b1 1c 1d 14 8a 0a 3e 5c ea ca ce 07 |.A`=......>\....| -00000300 d4 45 18 6c 16 52 40 6f b0 f4 33 38 d7 cf 11 75 |.E.l.R@o..38...u| -00000310 08 4e 7d 8b cc 64 8c 79 dd 42 fa 43 2c 9e 84 91 |.N}..d.y.B.C,...| -00000320 e9 d5 bc 9f 84 2d 10 4b db 4e a6 be 37 e9 2e 34 |.....-.K.N..7..4| -00000330 d7 3e a7 17 80 b5 cd 37 04 2a 6c 2a cc 5f 0c a1 |.>.....7.*l*._..| -00000340 ff c2 31 86 17 50 3a 47 4d 99 49 94 9c 11 12 e2 |..1..P:GM.I.....| -00000350 70 fa d1 f4 7e 3a f2 3a df 16 34 45 0a b2 7b 73 |p...~:.:..4E..{s| -00000360 fa 59 23 85 88 74 2b e6 1e cb c7 00 f5 96 c8 8a |.Y#..t+.........| -00000370 02 16 03 03 00 04 0e 00 00 00 |..........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 95 6f d7 |............ .o.| +000002d0 37 b9 49 ff 98 39 6f 25 c5 c0 e0 89 61 23 2d 22 |7.I..9o%....a#-"| +000002e0 5b 86 d6 7f a1 19 07 f7 12 4d 01 e6 1b 08 04 00 |[........M......| +000002f0 80 ca fd 6e 23 09 33 a7 0c 9b 4b 2b 38 37 a0 32 |...n#.3...K+87.2| +00000300 21 a4 e4 fe 56 b6 4e c6 d1 e6 86 fa d9 13 b4 f3 |!...V.N.........| +00000310 72 bf 31 ef c3 33 e9 99 a1 bf a4 e5 10 46 44 7d |r.1..3.......FD}| +00000320 cb ea 38 99 d0 bc 1f 16 81 fb ad 09 7e 9e 54 99 |..8.........~.T.| +00000330 40 c2 44 65 94 53 88 c3 28 db 7f 1b fa 52 f1 63 |@.De.S..(....R.c| +00000340 9a e9 f2 43 7f 19 2b 3e 02 3d 53 ed a1 f9 9a ff |...C..+>.=S.....| +00000350 aa af 8d 4c ab bf d2 7a b4 ea 1e f9 22 fe ee 7e |...L...z...."..~| +00000360 a1 3e dc d4 f1 76 d1 4e 7b 1b 84 f6 b3 a7 f7 a9 |.>...v.N{.......| +00000370 37 16 03 03 00 04 0e 00 00 00 |7.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 0a a7 0c 5f 47 d1 7c 5e ea 63 82 |.... ..._G.|^.c.| -00000040 83 27 6c bc 29 20 25 ec 3d 15 2d 59 94 e7 9d 2c |.'l.) %.=.-Y...,| -00000050 8b 4e 95 85 fc |.N...| +00000030 16 03 03 00 20 d0 64 37 7c 81 1c cd 86 e7 ab 97 |.... .d7|.......| +00000040 25 1d c5 ee bd 5a 49 44 69 c8 3e db 37 6a dc 9a |%....ZIDi.>.7j..| +00000050 fd e2 5e 82 16 |..^..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 03 84 99 6b f7 |.......... ...k.| -00000010 3e 44 b1 96 6a 09 75 bf 26 4b 67 30 c4 e9 86 74 |>D..j.u.&Kg0...t| -00000020 4d e1 e3 9b fa 15 8e 1e 72 f9 5a |M.......r.Z| +00000000 14 03 03 00 01 01 16 03 03 00 20 18 71 b3 67 a3 |.......... .q.g.| +00000010 98 36 20 8f e4 17 30 e4 73 de 91 88 ef f7 f3 8a |.6 ...0.s.......| +00000020 c6 0e 5e b2 1f e2 e6 5a 52 f6 72 |..^....ZR.r| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 68 29 2f 1b 1c 9d 28 6e b6 e5 09 |.....h)/...(n...| -00000010 4a 77 96 23 20 da 67 9e 14 ec 6b |Jw.# .g...k| +00000000 17 03 03 00 16 20 c3 2a be 39 d2 7c 1c 83 30 cc |..... .*.9.|..0.| +00000010 7b cd 44 ae 2b e8 d4 19 50 69 81 |{.D.+...Pi.| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 66 e8 13 d1 b5 13 cf 5c 71 7b d9 |.....f......\q{.| -00000010 63 29 3d be 68 9f f4 ad 7b |c)=.h...{| +00000000 16 03 03 00 14 96 2f 3a b5 b5 56 c9 d5 38 c0 1a |....../:..V..8..| +00000010 eb 35 c5 b9 dd 1c 5b e6 50 |.5....[.P| >>> Flow 7 (client to server) -00000000 16 03 03 01 1a cb 21 91 08 de 08 87 fc 63 10 93 |......!......c..| -00000010 24 a3 83 e8 99 07 d5 03 19 61 4e 8e df dd d0 f6 |$........aN.....| -00000020 50 3c fd 14 23 67 cd 74 ad 87 9b b7 8f ee a2 23 |P<..#g.t.......#| -00000030 6c 2f 90 18 f4 01 6b 31 fe ca f7 65 f9 64 5a bc |l/....k1...e.dZ.| -00000040 49 3b 25 4c 35 59 50 f2 bc 70 cb 24 2f ec 47 12 |I;%L5YP..p.$/.G.| -00000050 b6 16 22 9e ce 3b fb 17 f9 59 4e 2f 5c 03 90 47 |.."..;...YN/\..G| -00000060 d5 e8 e9 eb d9 55 bf 8f 28 e8 72 e5 15 21 42 ba |.....U..(.r..!B.| -00000070 86 65 ac b4 f5 53 7e 98 38 39 b5 7d 2a 14 d6 7b |.e...S~.89.}*..{| -00000080 3e 69 9d dc 43 33 ed 0b 8a 77 14 54 9d b0 da 88 |>i..C3...w.T....| -00000090 3b 75 50 01 07 02 99 36 39 4f 01 ee 02 cf 05 a5 |;uP....69O......| -000000a0 71 75 03 3a a5 5c c4 ce 0e 1d ba dd 9d 79 c1 84 |qu.:.\.......y..| -000000b0 81 69 7c cd 63 a4 20 a3 a2 13 8e 6e d7 01 29 8d |.i|.c. ....n..).| -000000c0 35 e2 fa 3d 74 ea 40 06 7e 0b 2d ab 3c 54 73 ef |5..=t.@.~.-....&.FU........| -00000110 43 bd e5 9f 5c 35 02 25 54 17 89 c0 be ab bc |C...\5.%T......| +00000000 16 03 03 01 34 ae 4f 4c 78 20 df 3b 9e f3 c1 82 |....4.OLx .;....| +00000010 37 6b ca fc 48 2a 2c 9a 71 7e c3 20 a0 e8 f7 d5 |7k..H*,.q~. ....| +00000020 76 af 11 81 dd 69 e9 93 58 df 58 8c fb f1 82 ad |v....i..X.X.....| +00000030 35 0e fb 6c a9 58 7a 5d 79 38 cb d7 77 1f 93 34 |5..l.Xz]y8..w..4| +00000040 7e bb 88 61 9e 19 1a 98 bb 6f ad 78 2c a6 73 ab |~..a.....o.x,.s.| +00000050 a4 7e 4b d7 75 69 7b 92 47 68 3d 7b 40 03 60 59 |.~K.ui{.Gh={@.`Y| +00000060 2e 04 bc cd fc ca 45 2c 2c f7 e5 0a 66 49 0b 86 |......E,,...fI..| +00000070 c5 ec 86 e6 ae c9 39 4b 05 1f 21 db 78 8d 51 e6 |......9K..!.x.Q.| +00000080 5d fe be 6a 1d 85 e1 15 23 56 86 4c ba 09 bf 7b |]..j....#V.L...{| +00000090 9e 36 e9 7a 8f 06 af 10 7b 4a 4b af 58 db f9 4e |.6.z....{JK.X..N| +000000a0 13 36 61 f4 e3 a9 c6 37 11 d4 ed 9e 6a c7 bf 16 |.6a....7....j...| +000000b0 ea a4 ae 01 99 4a b5 3e 9c ca 6c ce e8 a2 3d b8 |.....J.>..l...=.| +000000c0 81 ef 60 7b 51 79 81 22 87 49 ad ab fb c6 f6 48 |..`{Qy.".I.....H| +000000d0 c0 ba e0 2b d7 90 42 f7 a8 0d f0 cf 2c 7a 55 7d |...+..B.....,zU}| +000000e0 be 65 a6 67 bd 96 7f 01 6f ce db f6 50 2f 45 b6 |.e.g....o...P/E.| +000000f0 6f cc 74 ba 6f 57 3b e3 a4 08 34 92 e6 ac e4 99 |o.t.oW;...4.....| +00000100 2e b6 9b 29 4d 26 dd 7f 5c f5 1b 7e 5e 5c fd f7 |...)M&..\..~^\..| +00000110 d4 da 81 47 51 8c 3f 94 e1 95 5b de b9 6e 4a 76 |...GQ.?...[..nJv| +00000120 bc 59 6a bb 1f 1c 79 02 93 2e 21 b3 6d be ae b4 |.Yj...y...!.m...| +00000130 95 6b 8a 48 cb 84 fb ab b3 |.k.H.....| >>> Flow 8 (server to client) -00000000 16 03 03 00 85 10 dc 85 7d 1e 66 b2 a4 86 68 a7 |........}.f...h.| -00000010 31 f3 b1 d8 c7 c9 26 6d 74 0a c0 c0 c0 39 ad b5 |1.....&mt....9..| -00000020 1b b1 dc d3 15 9f a4 96 27 dd 65 85 ad 83 2f 97 |........'.e.../.| -00000030 42 6f 8a 9b 58 fc f8 1b 54 89 cd 9c 11 10 b9 1d |Bo..X...T.......| -00000040 c3 e1 8e 89 20 a5 2d 0b 31 b5 e0 16 54 ce 93 9b |.... .-.1...T...| -00000050 de cc b1 af 48 48 33 96 4d a6 00 78 7b 60 3f 7c |....HH3.M..x{`?|| -00000060 cd 86 64 5e 38 e8 fd 60 d4 b1 89 cd e4 fb 42 b5 |..d^8..`......B.| -00000070 82 8f e5 23 91 87 6d 54 9e 85 37 34 df ae 70 a5 |...#..mT..74..p.| -00000080 cd 4c de 95 f7 9f a9 b4 87 0b 16 03 03 02 69 d1 |.L............i.| -00000090 c2 87 4e c8 26 b3 89 88 da c0 b9 24 84 88 c0 76 |..N.&......$...v| -000000a0 94 08 eb 56 5d fc 96 81 18 f3 5b 90 f1 38 e5 ae |...V].....[..8..| -000000b0 b5 4e 9a c1 19 19 1a b3 40 55 08 cb 0e 3b 93 b3 |.N......@U...;..| -000000c0 d7 74 80 3a 7c 0d eb be 70 0e a9 50 88 d2 52 11 |.t.:|...p..P..R.| -000000d0 2d 55 cf d9 9d aa 92 bd 15 ab 1a 62 b3 26 09 3f |-U.........b.&.?| -000000e0 50 2b b8 f2 00 a2 5a 2b 98 e3 bb e2 c7 0b 07 0e |P+....Z+........| -000000f0 5a e5 2e 08 27 87 f3 0b 1b f7 f7 82 49 cf 08 d6 |Z...'.......I...| -00000100 7c 78 39 0e 92 e7 28 f4 8f 12 ac 6a c2 72 46 e8 ||x9...(....j.rF.| -00000110 92 bf 36 c7 52 46 7a 01 92 6d a9 08 19 2a 07 70 |..6.RFz..m...*.p| -00000120 8c b2 40 7d 7f 00 27 ea fb e6 24 5c d2 d8 ae 99 |..@}..'...$\....| -00000130 0b cc 2a 4b 35 12 de 85 e9 b5 e2 2d 80 39 6d 17 |..*K5......-.9m.| -00000140 7a ca ef ca bb 58 1e 13 86 10 bc 4d 8a df 32 ba |z....X.....M..2.| -00000150 3b 7e f5 40 ec af 2e 63 be f3 38 02 a9 9d 30 1f |;~.@...c..8...0.| -00000160 c4 d2 04 93 df e1 8a bb 5d f0 6a a8 d9 b9 ad bf |........].j.....| -00000170 da d6 5e bd a1 a8 b8 20 91 26 ab 50 fd 2b bf e1 |..^.... .&.P.+..| -00000180 56 33 e3 e4 4f 3f 21 ea 86 10 e9 35 84 03 70 0b |V3..O?!....5..p.| -00000190 bd dc 44 fc 58 1d bc 9e 3a 0d 3b 61 13 d6 33 1b |..D.X...:.;a..3.| -000001a0 97 a8 67 bf e6 d9 1d 34 69 70 93 4a 6c 28 88 01 |..g....4ip.Jl(..| -000001b0 01 9d 78 59 c0 58 66 c3 70 e4 ba 74 e6 0f f7 27 |..xY.Xf.p..t...'| -000001c0 8b dd 05 ac 0d 99 dc e9 c8 2f 16 ee 59 53 91 d7 |........./..YS..| -000001d0 28 27 db ad 85 e6 d0 72 28 81 31 e1 e7 bf dd 95 |('.....r(.1.....| -000001e0 75 ff d6 a9 dc 4f 30 37 52 07 87 cb 8d a7 4a 00 |u....O07R.....J.| -000001f0 22 53 3c 6d 91 94 11 5d 0a a8 21 ea 1f 18 4e 42 |"S...A...| -00000390 37 c3 62 b5 30 89 4d b6 6c 5c f2 8c ff 3c 2e 48 |7.b.0.M.l\...<.H| -000003a0 bf 0f 5f 3e e0 b2 d7 64 2b dc 42 ad 2f 83 b5 6b |.._>...d+.B./..k| -000003b0 5a 04 51 f8 c4 07 c2 61 e4 16 03 03 00 4a a9 18 |Z.Q....a.....J..| -000003c0 58 79 d8 ad 86 d7 b6 77 39 76 99 b4 0a 29 72 b1 |Xy.....w9v...)r.| -000003d0 eb c3 ec 95 4d 30 4c 21 1a 7f 52 da 56 21 78 b7 |....M0L!..R.V!x.| -000003e0 fe dd d3 0e fc a9 89 40 99 97 12 68 7e 28 6e 32 |.......@...h~(n2| -000003f0 5b c0 e8 b4 42 eb ee 83 c2 ae 0d 28 99 48 46 a9 |[...B......(.HF.| -00000400 64 38 60 59 c2 dc 5c 7b 16 03 03 00 14 78 72 cf |d8`Y..\{.....xr.| -00000410 ac 5d 53 7e 73 b1 6e e2 0a 8e 12 33 be 03 86 6a |.]S~s.n....3...j| -00000420 ce |.| +00000000 16 03 03 00 85 60 c6 c2 9b 61 f1 1f 81 6f f1 0b |.....`...a...o..| +00000010 87 2d f2 93 a6 4e 7e 74 c2 61 cf 1d a1 00 32 8f |.-...N~t.a....2.| +00000020 f7 3d 93 da 91 cc 5b d5 21 c6 ba 4c 1b eb 81 a9 |.=....[.!..L....| +00000030 a1 2a fe 88 6d 3e 1d 1f 57 22 9c ff fe 6c 85 ca |.*..m>..W"...l..| +00000040 0b 13 f3 9f 63 55 b9 49 61 2b dd 5e 2b e1 fd ec |....cU.Ia+.^+...| +00000050 1d 0d 94 06 42 dc 2c 6f 88 22 cb 30 4f 66 6f 16 |....B.,o.".0Ofo.| +00000060 3a a0 c0 23 12 82 46 38 70 68 e5 12 b9 16 12 e7 |:..#..F8ph......| +00000070 38 6b 50 64 55 f0 47 a9 e0 cd 19 01 8e d5 12 96 |8kPdU.G.........| +00000080 09 db 5c 52 4b db 9b 26 43 37 16 03 03 02 69 41 |..\RK..&C7....iA| +00000090 52 a8 ca e5 8f e0 33 4b 52 93 74 ef bb 42 20 d1 |R.....3KR.t..B .| +000000a0 cc 24 79 ce df 51 90 e0 19 b1 11 fb e9 ef b5 e4 |.$y..Q..........| +000000b0 ae da 72 e1 35 a8 41 88 a8 4b 68 d2 50 58 ba ef |..r.5.A..Kh.PX..| +000000c0 b0 1e 20 26 a3 c2 86 a7 68 60 84 2d 23 14 38 21 |.. &....h`.-#.8!| +000000d0 12 60 05 2f 79 9e c0 08 4c 87 a7 41 b3 d3 84 9a |.`./y...L..A....| +000000e0 f1 45 bd 2d ff 7c b5 bd c4 3a b1 48 10 9a d8 cf |.E.-.|...:.H....| +000000f0 ce 58 47 75 e1 6d 01 b6 18 bd 78 6b 86 a1 f2 1b |.XGu.m....xk....| +00000100 c8 03 4d 0a ce ce d4 68 8f 9a 54 1e 83 83 89 2c |..M....h..T....,| +00000110 36 a2 3a b5 95 09 de c5 8e 8c d0 a4 95 59 7e d6 |6.:..........Y~.| +00000120 f8 5f 96 e9 c5 cb 9b 6c c0 b7 55 15 b3 b4 d0 ea |._.....l..U.....| +00000130 bf 11 1c 89 1a 5c f2 09 74 9a 43 73 4f 6f 00 33 |.....\..t.CsOo.3| +00000140 b9 e0 6a 99 b9 e0 02 86 dd cd 07 68 72 63 0d 8b |..j........hrc..| +00000150 e0 e8 12 68 4d f6 3b dc 0a 93 82 48 ce f7 96 ba |...hM.;....H....| +00000160 7f c5 90 07 45 66 3d 47 b8 8d 5f 0d 41 8d 88 76 |....Ef=G.._.A..v| +00000170 bf ce 9c 2a 2e 25 7c 47 f6 96 73 0b 43 42 73 2c |...*.%|G..s.CBs,| +00000180 d5 b3 bc 82 c5 19 2f 5d c4 69 21 7d c8 7b 1b b8 |....../].i!}.{..| +00000190 b6 d1 37 89 92 a6 b7 44 cd e6 23 1f a1 03 08 05 |..7....D..#.....| +000001a0 1e cf 54 78 e9 af 04 bc e3 94 aa 12 ce 67 62 ce |..Tx.........gb.| +000001b0 f4 2f ef f7 2b 8d 65 06 08 07 2f c6 fa b2 d2 c8 |./..+.e.../.....| +000001c0 f1 d7 c4 1f cc 8b 0e b8 f2 b2 1d fb 09 19 5a b0 |..............Z.| +000001d0 a3 23 6e 05 20 9a 28 39 16 05 0e c4 7d d0 59 f5 |.#n. .(9....}.Y.| +000001e0 9a de 88 da a2 c0 fb 7b 84 19 05 7d 80 6f 9a 03 |.......{...}.o..| +000001f0 0a f8 5f 97 a2 b4 c0 d9 6d 79 f5 c0 51 d3 63 d2 |.._.....my..Q.c.| +00000200 b8 ee a6 b0 76 59 7f 92 6d ad 3c bb 96 34 ac 0c |....vY..m.<..4..| +00000210 81 61 c5 07 7e 65 f1 c3 dd 3e 69 ad ee 7f 56 8d |.a..~e...>i...V.| +00000220 d7 92 48 5c 23 be 94 44 2e 8a 13 76 ce a3 cb d2 |..H\#..D...v....| +00000230 86 d5 eb 2c 48 55 fd 31 c1 94 08 55 69 8c 20 cd |...,HU.1...Ui. .| +00000240 65 fa 47 5e 8e 7f 04 a4 a0 54 c3 cf 4e b5 a0 61 |e.G^.....T..N..a| +00000250 3a 66 fd 21 5d 42 ab b3 46 d8 2a 64 69 1a d3 da |:f.!]B..F.*di...| +00000260 41 65 2c 36 50 f1 79 c3 83 01 d2 87 41 d9 10 1d |Ae,6P.y.....A...| +00000270 75 a2 74 de 48 e3 9c 9e c8 96 58 45 43 82 dd d6 |u.t.H.....XEC...| +00000280 e1 46 66 2f 13 e4 1d fe 81 8f ea 3d 6d 83 d7 97 |.Ff/.......=m...| +00000290 4d ed c6 67 0e 4b e5 a1 ca 2b 24 c5 b1 24 af df |M..g.K...+$..$..| +000002a0 7a 0e 44 b9 c1 5f 07 43 c1 6f 94 d3 22 fb 14 df |z.D.._.C.o.."...| +000002b0 a3 23 38 c9 91 ff 12 41 fa 47 f7 83 fb b6 ca ea |.#8....A.G......| +000002c0 19 01 22 8a ba d7 86 c5 d2 82 2f ac f5 4c a4 e9 |.."......./..L..| +000002d0 90 f5 52 c7 88 96 ae f3 0a 91 53 1c db bf 4b a9 |..R.......S...K.| +000002e0 42 43 0d 2d cc f2 6a 79 1e 9a 3a bd 55 da 5d 6c |BC.-..jy..:.U.]l| +000002f0 a3 84 79 76 7d 96 62 5e 16 03 03 00 bc 51 62 b9 |..yv}.b^.....Qb.| +00000300 26 c9 f7 dd 55 83 aa cd 90 5d e9 9a 29 92 8c 6f |&...U....]..)..o| +00000310 b1 df 4c b7 be 75 89 2b dc b1 ad ae 01 38 27 0f |..L..u.+.....8'.| +00000320 36 43 0b 04 69 6b a4 3a 52 b5 4f df 50 1d 04 ee |6C..ik.:R.O.P...| +00000330 4a f1 a0 6c 06 6f 24 2a f3 dc 7c a4 96 12 e2 83 |J..l.o$*..|.....| +00000340 9c d8 2d 63 2e 3b 1c 73 e6 32 ce 15 76 01 9a a9 |..-c.;.s.2..v...| +00000350 3b a7 dc aa 40 82 4d 5a 68 24 78 4e fe 64 db a4 |;...@.MZh$xN.d..| +00000360 ff 87 6d 90 bc d9 ec 0d ed 8b 54 12 bd 74 16 1d |..m.......T..t..| +00000370 2c 30 57 8f 67 56 7c 09 e6 b1 12 f8 4a 9f e3 79 |,0W.gV|.....J..y| +00000380 c1 8b fa 91 f7 1a 29 bd a3 1f 59 59 16 26 04 10 |......)...YY.&..| +00000390 e4 19 c9 91 a6 b3 c5 b5 df a3 b0 11 a5 87 29 4e |..............)N| +000003a0 5b 9f 96 cf 88 19 9e ae b4 e6 63 19 6d c5 ee 7a |[.........c.m..z| +000003b0 c9 38 2d 0a fd f6 3b f8 f5 16 03 03 00 4a f5 3f |.8-...;......J.?| +000003c0 ef a3 f8 86 1b f5 ce 8e 48 f2 d0 cb 75 d6 80 b2 |........H...u...| +000003d0 78 ef bc 77 a6 aa 91 cd 88 39 62 f8 42 78 7c f3 |x..w.....9b.Bx|.| +000003e0 8b c7 86 71 9c a5 9f 1c 5f 40 25 e9 c6 69 82 a1 |...q...._@%..i..| +000003f0 45 ee d1 9d f7 9c a0 b9 34 b8 82 72 f9 f8 1d fb |E.......4..r....| +00000400 a5 74 b5 a5 68 04 82 c4 16 03 03 00 14 07 9c 37 |.t..h..........7| +00000410 77 ad 83 27 66 2c 3a ba 26 22 2f 72 b4 d1 c8 c1 |w..'f,:.&"/r....| +00000420 06 |.| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 33 a1 bb 7d ff 23 ba ad dc a0 1e |....i3..}.#.....| -00000010 3c 7c 1f 53 59 81 13 04 49 f7 6e bf 8f ef 11 92 |<|.SY...I.n.....| -00000020 51 bf 8a e7 fe ef 76 e4 f8 88 27 95 f4 12 f2 ed |Q.....v...'.....| -00000030 cc ec a6 2d 10 87 19 5e c9 fe cd 12 ae 1a 38 f9 |...-...^......8.| -00000040 78 f1 42 f8 47 26 1b c2 5f 82 a5 aa 65 17 eb 06 |x.B.G&.._...e...| -00000050 03 c8 22 9c 9f 8b 87 26 4a 64 18 93 9c f4 16 82 |.."....&Jd......| -00000060 28 eb 8d 2d f8 51 60 3a f4 bb a3 77 f5 97 2b 6a |(..-.Q`:...w..+j| -00000070 19 db 2e 46 8b d8 08 d8 28 88 bb bd d8 3b c2 bb |...F....(....;..| -00000080 8c 87 1b 17 a0 34 a8 c6 e8 a5 a0 e5 cb d6 9c 9d |.....4..........| -00000090 a6 a4 6c 06 6a 85 0c 5e ef 0c 97 6f b6 11 e7 4d |..l.j..^...o...M| -000000a0 60 91 95 74 48 af 1b 0b 47 03 ed 47 e9 b9 28 36 |`..tH...G..G..(6| -000000b0 74 0d 8a b8 1e 5d 1c cb ea 7b b7 8f 18 e3 b9 b9 |t....]...{......| -000000c0 43 ed 53 f2 bf 7e 8c 8f e6 c0 2a f4 31 25 f5 e8 |C.S..~....*.1%..| -000000d0 44 48 2d 36 4f a7 11 f6 ea 7c 3f d6 2d 5d 3e 39 |DH-6O....|?.-]>9| -000000e0 fb 50 f1 c9 eb 25 be 7a c5 af 54 f5 12 07 04 22 |.P...%.z..T...."| -000000f0 ec 68 45 f1 fd d1 91 0a cf 64 0f f3 58 4e e8 ce |.hE......d..XN..| -00000100 f6 9e c0 57 ea 3a bd a0 5d 26 d4 ab ed 1a 34 12 |...W.:..]&....4.| -00000110 9f fa ec 73 d6 38 06 78 85 3c f9 cd aa fb fd 32 |...s.8.x.<.....2| -00000120 cb e0 a7 d0 bb 71 b0 a3 d2 b9 89 5e a9 57 18 7e |.....q.....^.W.~| -00000130 c0 c9 2e e3 e5 07 65 6f 4c ad 22 78 50 f2 87 0f |......eoL."xP...| -00000140 cd 93 b3 19 a9 73 e2 1d bf 38 a0 20 8d 3a 3a 4e |.....s...8. .::N| -00000150 b3 02 b7 11 1f df 12 60 dd 10 1c f8 75 4a 52 86 |.......`....uJR.| -00000160 71 61 88 37 b3 bf f7 2d 45 6d 10 4a 9f 80 b3 fc |qa.7...-Em.J....| -00000170 36 d4 d3 9f 08 f2 bb ce 9c 3a 9a 59 f6 0a 0a aa |6........:.Y....| -00000180 7f 61 29 0b df 29 92 09 55 ec 1c 84 d6 1f 7c 68 |.a)..)..U.....|h| -00000190 72 00 88 5e e3 6a ee 35 45 7a 0b 49 35 0e 2d 7c |r..^.j.5Ez.I5.-|| -000001a0 ac 8b 9f 9c 94 48 2d 1e 74 24 68 14 8e 16 b4 06 |.....H-.t$h.....| -000001b0 24 66 a3 18 f4 ff 21 31 4b 9b bb 09 8a 9d 57 e4 |$f....!1K.....W.| -000001c0 a1 5c ae f1 e1 4b 5c 2a be 64 3c 7a 61 10 3d 73 |.\...K\*.d....^O| -000002f0 f7 4b 38 70 d0 82 42 f2 5a c9 34 d2 76 7b 8d e4 |.K8p..B.Z.4.v{..| -00000300 0b c7 3d be 86 7d 21 8c f8 9f 1a 4a dc 48 07 12 |..=..}!....J.H..| -00000310 ab 4c 98 f7 8b 3e 02 49 c2 d1 b5 e9 9a e0 5a 74 |.L...>.I......Zt| -00000320 58 ce a3 33 be 0f ca 12 54 a2 0e a9 e5 22 8f 82 |X..3....T...."..| -00000330 df 1a 3e 21 bf 66 c6 13 39 77 83 95 b1 4b 1d d3 |..>!.f..9w...K..| -00000340 32 69 24 c2 89 14 03 03 00 11 1c eb 63 31 c9 c9 |2i$.........c1..| -00000350 8a e3 8b 25 7e e9 b7 7d 19 03 3c 16 03 03 00 20 |...%~..}..<.... | -00000360 c6 41 57 04 ab e8 6c 55 0b dc cd 06 f5 b3 4b 95 |.AW...lU......K.| -00000370 40 b5 04 47 da 71 d7 70 ce d6 2e 0b c7 66 16 3c |@..G.q.p.....f.<| +00000000 16 03 03 02 69 70 78 66 7a 28 3b 50 a6 21 b2 cc |....ipxfz(;P.!..| +00000010 52 a6 74 f7 29 8a dc fd c0 1c 79 d0 20 23 d0 74 |R.t.).....y. #.t| +00000020 d3 16 a6 4c 6d df 6e 32 2e 69 46 dd 8d 22 9e 8e |...Lm.n2.iF.."..| +00000030 cb 75 44 75 7e 24 69 ed ce cf 5c 4b a9 a2 b5 d0 |.uDu~$i...\K....| +00000040 48 bf 08 d8 1d 16 d9 9f 6d b4 24 ee f1 f3 58 79 |H.......m.$...Xy| +00000050 4c 19 4c 99 7f 01 a8 80 b1 3c 4e 55 d1 64 75 89 |L.L......?.Pjad*Q...| +00000120 01 2e 5a 1c 8b 12 58 c5 32 e1 3f ea 0b ac 4c 3b |..Z...X.2.?...L;| +00000130 1d 97 11 e9 92 6d 52 f0 1e f7 5a f8 71 5f f5 a6 |.....mR...Z.q_..| +00000140 6b aa 30 4f 85 41 c6 49 83 37 3a 72 86 1a be 7a |k.0O.A.I.7:r...z| +00000150 1d bc d6 ad 67 6c 95 42 5d 74 10 8e ac 4b 8d b3 |....gl.B]t...K..| +00000160 6e 3d 9c 8f 08 71 be ce ce aa 64 26 62 2a 58 8c |n=...q....d&b*X.| +00000170 e4 7b 75 e9 61 90 38 b2 c2 a0 8d c7 a9 11 cf 5b |.{u.a.8........[| +00000180 30 a7 33 3b 2b c2 fd 2a 6b db 3d cf 35 6c 23 28 |0.3;+..*k.=.5l#(| +00000190 14 e4 7b 10 50 e8 00 9f af 60 69 cf a9 d9 93 f3 |..{.P....`i.....| +000001a0 8f 7d 39 49 97 5b 92 4a 35 2a 6c 68 3b 48 25 77 |.}9I.[.J5*lh;H%w| +000001b0 6e d0 57 76 c4 94 83 10 e3 3d 00 e8 b9 fe da d9 |n.Wv.....=......| +000001c0 a5 56 22 61 e0 f4 33 dd c8 dd 4d 2f 39 51 35 12 |.V"a..3...M/9Q5.| +000001d0 9a cb dd e1 03 d3 27 9f 41 71 83 5c c7 6c a3 38 |......'.Aq.\.l.8| +000001e0 9f db 39 1c 2a f6 4b e0 48 44 61 1b 34 3c bc ed |..9.*.K.HDa.4<..| +000001f0 7a 31 c9 9f 8e 82 2d fb b6 bd 6e 4c 57 76 23 f5 |z1....-...nLWv#.| +00000200 7d 68 ff 02 75 42 10 e7 2d 24 83 4a 04 7a 78 d7 |}h..uB..-$.J.zx.| +00000210 60 b2 70 07 3f e4 bc 54 42 65 22 c3 2e aa 35 85 |`.p.?..TBe"...5.| +00000220 df fa e5 c9 c9 f5 ee 6a 50 82 7a bf 92 96 78 5e |.......jP.z...x^| +00000230 a8 ac 2a d1 5e e2 f0 20 6b 51 97 3d 74 71 eb d8 |..*.^.. kQ.=tq..| +00000240 40 5f 06 72 b6 8c 1c 2a 71 dd 53 38 fb de b6 31 |@_.r...*q.S8...1| +00000250 53 8d 8f 4e 0f c1 a5 ea bf 27 fa ed ff 0c 56 34 |S..N.....'....V4| +00000260 55 88 e1 d2 65 a7 e5 10 02 4d ba 8e ad fa 16 03 |U...e....M......| +00000270 03 00 35 94 36 93 c6 5e c8 ec 8e 63 86 7b 13 d6 |..5.6..^...c.{..| +00000280 78 b2 5d 2f 54 55 5a 41 1c 65 5e b2 69 ab c2 bd |x.]/TUZA.e^.i...| +00000290 d9 a3 55 42 d1 96 29 51 c4 38 c4 ec 1f d4 19 6c |..UB..)Q.8.....l| +000002a0 2b 82 75 81 37 07 79 35 16 03 03 00 98 d9 a2 ba |+.u.7.y5........| +000002b0 86 ca f4 24 e1 e0 72 0e 21 81 f6 c5 d7 0a 1c 17 |...$..r.!.......| +000002c0 05 1f ce b8 4d d3 d8 e6 13 c8 a6 4d f3 da 0f 4d |....M......M...M| +000002d0 e3 21 29 84 78 90 fa 11 a5 06 19 3a cd ca f2 1f |.!).x......:....| +000002e0 a2 39 4d b3 03 8d 22 27 eb bc f4 8b b8 61 c0 f3 |.9M..."'.....a..| +000002f0 70 34 56 80 28 a2 85 1e 21 7c 11 b8 c6 0c 0d bd |p4V.(...!|......| +00000300 02 56 8a b5 d5 7b 22 97 3e 70 20 31 00 a0 16 2d |.V...{".>p 1...-| +00000310 87 b5 c7 b0 5e 40 2d 08 82 97 38 64 c4 14 e3 16 |....^@-...8d....| +00000320 0d 6f d1 b1 6b 5f 7c 14 18 66 67 aa 8a b6 6b 66 |.o..k_|..fg...kf| +00000330 7d e3 68 ca 97 13 ad ca 0a 46 06 6b 4a a9 c0 ee |}.h......F.kJ...| +00000340 8b 61 6d 2d cc 14 03 03 00 11 93 6d 0b 63 c5 e2 |.am-.......m.c..| +00000350 3f 0f da dd f4 7c ae 95 2a e8 65 16 03 03 00 20 |?....|..*.e.... | +00000360 62 97 ee b8 34 aa be 0a 2c 24 30 6c 89 f2 80 08 |b...4...,$0l....| +00000370 05 69 bb ad a8 5c 90 21 04 77 96 44 ae 5f d4 d5 |.i...\.!.w.D._..| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 c0 4e fd fa 3a 1c 4a 19 ce 08 f6 |......N..:.J....| -00000010 da 70 56 fa 39 42 16 03 03 00 20 0c bc c4 5e 24 |.pV.9B.... ...^$| -00000020 e3 0e c9 23 8c cd f6 a2 45 07 e6 93 40 7c c8 02 |...#....E...@|..| -00000030 6e 24 f7 4e 06 9a ad ba de cd 10 17 03 03 00 19 |n$.N............| -00000040 52 e0 85 b3 46 25 7d fd 8f d0 4c ca df fe 2f a6 |R...F%}...L.../.| -00000050 14 d6 08 82 70 0f 93 78 bf 16 03 03 00 14 ff 68 |....p..x.......h| -00000060 f1 6d 8d b4 5f 74 19 6b e3 1e 6e ee 9d ee c2 34 |.m.._t.k..n....4| -00000070 0f 44 |.D| +00000000 14 03 03 00 11 03 06 35 7b 36 e4 b2 df 80 68 80 |.......5{6....h.| +00000010 df e3 d6 3c bb b7 16 03 03 00 20 08 9b ed a0 ae |...<...... .....| +00000020 e7 f9 42 9a f5 10 21 7a 38 dc a2 6d 27 a8 bc 00 |..B...!z8..m'...| +00000030 58 85 6a 85 04 b9 3b 3f ca 26 68 17 03 03 00 19 |X.j...;?.&h.....| +00000040 d5 24 ff 37 e7 a2 5d eb f2 45 ca 73 60 3b c3 8c |.$.7..]..E.s`;..| +00000050 87 10 d8 31 c3 a2 e5 3d 0f 16 03 03 00 14 31 8a |...1...=......1.| +00000060 c9 a6 3a 3e 36 e0 4f d6 f1 f5 67 70 34 8a ab dc |..:>6.O...gp4...| +00000070 82 e2 |..| >>> Flow 11 (client to server) -00000000 15 03 03 00 12 81 0d 63 a5 11 7a 03 ab 66 f6 c8 |.......c..z..f..| -00000010 15 f3 d9 23 fa 67 6b 15 03 03 00 12 71 0e 3b 52 |...#.gk.....q.;R| -00000020 1a 05 39 4c 8c 76 c3 a9 00 35 bd 66 80 a1 |..9L.v...5.f..| +00000000 15 03 03 00 12 be b2 bb cf 44 91 f3 b9 71 00 af |.........D...q..| +00000010 9e b6 f5 07 64 36 7b 15 03 03 00 12 ae b2 33 16 |....d6{.......3.| +00000020 de f1 45 31 a5 fd 07 97 6e 57 f8 22 cc b2 |..E1....nW."..| diff --git a/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected b/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected index 0be2e72bf3c..c907c7cb2ea 100644 --- a/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected +++ b/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 21 15 e1 02 00 |....]...Y..!....| -00000010 c6 0c e5 3f c9 6f a5 59 38 7e 13 81 1b 26 50 46 |...?.o.Y8~...&PF| -00000020 bf 2b 95 0c eb a8 bc 72 97 bc 26 20 ad 6b 84 ac |.+.....r..& .k..| -00000030 8f 62 26 0b 4b d8 bf 1b 7d a5 27 3b 3e 45 a5 8f |.b&.K...}.';>E..| -00000040 37 fb b2 25 2c d3 82 69 ed d7 c9 f0 cc a8 00 00 |7..%,..i........| +00000000 16 03 03 00 5d 02 00 00 59 03 03 ea a3 8e 85 79 |....]...Y......y| +00000010 9f 41 1f 7e 05 76 70 3d bd f4 bb f4 dd 49 a6 fd |.A.~.vp=.....I..| +00000020 11 83 a9 70 89 86 87 36 2f 09 b9 20 1a 00 de fc |...p...6/.. ....| +00000030 6b e5 93 4e da 98 0b e1 a8 93 8d fc 4b c3 48 6b |k..N........K.Hk| +00000040 15 6d de fd e3 0f 36 67 61 1c 91 8e cc a8 00 00 |.m....6ga.......| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -61,36 +62,36 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 b2 3a 28 |............ .:(| -000002d0 2e 2c 66 f1 9b 44 58 9a 92 03 42 81 f6 1c f4 67 |.,f..DX...B....g| -000002e0 50 b5 92 f3 06 1b 1b 23 93 99 12 c5 6b 08 04 00 |P......#....k...| -000002f0 80 44 05 ae 8d ed c6 82 3a 2a 19 05 9d 70 f9 ba |.D......:*...p..| -00000300 45 66 cb 45 75 9c da 92 cc bb 4a a5 ae 41 8c f8 |Ef.Eu.....J..A..| -00000310 9b e7 06 73 88 9f f9 7d 95 ce 74 a6 05 e9 38 a5 |...s...}..t...8.| -00000320 26 4b b2 26 31 5c e9 f9 a8 f8 6e 6b 05 e4 39 b5 |&K.&1\....nk..9.| -00000330 fe b1 b1 cd 40 23 e9 68 f3 9c ed 91 71 d3 0b c5 |....@#.h....q...| -00000340 91 c5 b2 91 69 a9 4b 2c a7 0c 24 d6 a9 e7 74 89 |....i.K,..$...t.| -00000350 9e ce 8b 00 72 9a c9 86 8b ca 8d 39 01 a0 71 3e |....r......9..q>| -00000360 46 ff a6 7d c6 da 0a af f2 84 c4 01 1c 94 47 22 |F..}..........G"| -00000370 71 16 03 03 00 04 0e 00 00 00 |q.........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 6a e1 91 |............ j..| +000002d0 5d 5d fe 77 50 be a5 52 f1 12 43 30 34 aa 46 87 |]].wP..R..C04.F.| +000002e0 f9 6a 80 37 eb 46 fb 92 d6 ce 18 c4 0b 08 04 00 |.j.7.F..........| +000002f0 80 46 10 ab ff 45 fe c5 88 5a da d0 07 b5 a1 30 |.F...E...Z.....0| +00000300 03 d8 b0 5f 88 37 45 75 ef b7 96 5c c9 1f 47 14 |..._.7Eu...\..G.| +00000310 24 28 de cf 1f c9 c6 a4 0c 41 1b 51 70 7a e6 e8 |$(.......A.Qpz..| +00000320 88 1b 35 ce 63 e7 4f 2b 02 c9 35 0a 56 b2 2a 59 |..5.c.O+..5.V.*Y| +00000330 e9 02 53 11 82 f2 f6 18 06 3a 3e 2e 8e 21 78 9d |..S......:>..!x.| +00000340 41 43 e2 ed 49 ce 87 cd 93 b7 13 6c 35 6e 4e 95 |AC..I......l5nN.| +00000350 68 1b 4b 75 de fa ed 48 53 56 54 40 5f 3f 36 cb |h.Ku...HSVT@_?6.| +00000360 6b 57 de 3c fc 51 f4 fb 9d 8d 55 2e e9 ce fc 79 |kW.<.Q....U....y| +00000370 08 16 03 03 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 80 26 44 1c a7 83 b7 12 29 9a 44 |.... .&D.....).D| -00000040 7b c1 0b 96 53 c8 0e 9b dd 8d 29 4b 4b b8 75 d7 |{...S.....)KK.u.| -00000050 0a c7 86 c7 d9 |.....| +00000030 16 03 03 00 20 be b4 f9 49 91 3c c8 f8 7c da ef |.... ...I.<..|..| +00000040 06 bd d5 9e d3 b4 74 f6 22 2e b8 5c b6 e2 2d 01 |......t."..\..-.| +00000050 cb d5 3f 94 7f |..?..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 2e d7 9e b0 66 |.......... ....f| -00000010 f1 39 84 a9 d9 93 17 bd 94 5a 31 49 bb eb f0 a0 |.9.......Z1I....| -00000020 7b af d0 3b ae 1a 5d f6 46 31 36 |{..;..].F16| +00000000 14 03 03 00 01 01 16 03 03 00 20 21 a2 e6 72 21 |.......... !..r!| +00000010 6d 45 36 87 6d 3f c9 70 89 1f b3 0a cc c2 5b 18 |mE6.m?.p......[.| +00000020 27 37 d8 1f 4e 55 f9 9d 07 96 2f |'7..NU..../| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 cd 39 a7 64 3b 6a de 14 e0 26 ea |......9.d;j...&.| -00000010 66 b2 73 b1 8e b0 e3 a9 94 62 4f |f.s......bO| +00000000 17 03 03 00 16 81 33 71 a4 ec a6 67 b2 17 ba 80 |......3q...g....| +00000010 27 80 a1 62 fb 1e ab 3f cd b9 fe |'..b...?...| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 c5 d7 88 58 81 44 1f 8d e4 c2 19 |........X.D.....| -00000010 15 3b 5c 43 76 82 fe 03 e1 |.;\Cv....| +00000000 16 03 03 00 14 b3 2b 93 6f bc d1 11 45 fa 9a d3 |......+.o...E...| +00000010 f3 82 75 6c ce 40 38 21 5e |..ul.@8!^| >>> Flow 7 (client to server) -00000000 15 03 03 00 12 d4 b1 0d fa 41 25 ab d4 e1 b7 74 |.........A%....t| -00000010 27 5c 8b c6 0d 49 8e 15 03 03 00 12 65 3d 4e 30 |'\...I......e=N0| -00000020 48 43 8f f6 8b 89 45 af f4 7a e4 eb ad a1 |HC....E..z....| +00000000 15 03 03 00 12 48 45 72 03 40 44 98 c6 db 40 d4 |.....HEr.@D...@.| +00000010 a6 9b 67 5d 8b c1 a9 15 03 03 00 12 21 d2 4b 7d |..g]........!.K}| +00000020 51 c7 3c 53 0b d9 67 90 aa e6 42 e2 8c 83 |Q.>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,21 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 01 ca 02 00 01 c6 03 03 da b0 57 a0 ee |.............W..| -00000010 bf 74 92 06 39 a6 9a 9b 80 71 7e 57 63 ab 31 74 |.t..9....q~Wc.1t| -00000020 d3 22 c1 e3 a6 c6 cf 6f 47 57 49 20 86 52 fb 0a |.".....oGWI .R..| -00000030 fd aa 10 47 00 9a 5d ad 4c d8 90 f1 cf 13 10 73 |...G..].L......s| -00000040 31 f1 df 22 f3 42 58 b0 10 25 43 eb cc a8 00 01 |1..".BX..%C.....| +00000000 16 03 03 01 ca 02 00 01 c6 03 03 28 44 55 f3 f5 |...........(DU..| +00000010 c1 63 ac 0b fd 1c 29 d3 90 a5 5c 96 2a d9 13 20 |.c....)...\.*.. | +00000020 fe 96 11 3f 30 0a e1 a9 8e d9 e6 20 ca 40 de 01 |...?0...... .@..| +00000030 4f 00 88 88 41 0f df af 85 0e 0e 22 9d a7 46 e8 |O...A......"..F.| +00000040 df 9c 8e 8c 47 5b 94 91 94 06 f4 14 cc a8 00 01 |....G[..........| 00000050 7e 00 12 01 69 01 67 00 75 00 a4 b9 09 90 b4 18 |~...i.g.u.......| 00000060 58 14 87 bb 13 a2 cc 67 70 0a 3c 35 98 04 f9 1b |X......gp.<5....| 00000070 df b8 e3 77 cd 0e c8 0d dc 10 00 00 01 47 97 99 |...w.........G..| @@ -84,31 +85,31 @@ 00000400 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b |Cw.......@.a.Lr+| 00000410 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 |...F..M...>...B.| 00000420 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 |..=.`.\!.;......| -00000430 00 ac 0c 00 00 a8 03 00 1d 20 0e e6 72 88 cf d1 |......... ..r...| -00000440 05 c7 8d 03 64 b9 db d8 c3 5e 36 80 67 67 36 94 |....d....^6.gg6.| -00000450 5b b7 92 f9 77 1f 6f b2 44 7f 08 04 00 80 1d 3b |[...w.o.D......;| -00000460 70 d5 72 87 2f 58 20 da 29 e0 f8 e8 7c 8d e5 c7 |p.r./X .)...|...| -00000470 bf da 3c 10 f8 b0 3e 38 7b 06 0b 8e 8f d7 40 b6 |..<...>8{.....@.| -00000480 47 9f 1c 64 6e 80 ab 9d 51 92 8c 60 a2 88 c4 43 |G..dn...Q..`...C| -00000490 7d dc 29 64 45 83 a7 9c 2a 39 e9 bb 2a d9 f5 96 |}.)dE...*9..*...| -000004a0 4c fb fd 0d cc 0f 9b 48 f5 ee af 8f 7a 1c 39 3e |L......H....z.9>| -000004b0 cf 23 15 c6 ab c3 f2 29 fd 6c 4f 17 6b d4 be 1a |.#.....).lO.k...| -000004c0 23 6e 74 81 e5 e5 e8 c0 de 9b b0 ed d2 32 bc 2a |#nt..........2.*| -000004d0 b1 30 b2 eb ac 9e 23 f8 be ea 31 9a b4 55 16 03 |.0....#...1..U..| +00000430 00 ac 0c 00 00 a8 03 00 1d 20 26 24 4e d8 a6 cc |......... &$N...| +00000440 2f c9 0e 68 d8 20 e3 97 5b c1 08 72 1e 79 46 d9 |/..h. ..[..r.yF.| +00000450 a6 00 9c e9 f8 21 9b cd 29 17 08 04 00 80 aa 6d |.....!..)......m| +00000460 36 bb 06 e6 11 66 82 44 87 5d 81 53 e2 9a 95 11 |6....f.D.].S....| +00000470 54 a3 cc a7 c9 9c 19 f6 da 98 4f 91 a6 dd 9e 10 |T.........O.....| +00000480 14 83 04 55 2d 6c 9a af 26 7c 5d f0 aa ca 69 83 |...U-l..&|]...i.| +00000490 af fe a5 cb a4 1a d4 bd 86 91 52 11 03 4d 9a ca |..........R..M..| +000004a0 37 fd 01 48 e8 5d a8 ea ad a2 a5 08 cb ce 5f 52 |7..H.]........_R| +000004b0 92 30 83 de 77 2a 06 c2 f2 53 4d 47 40 b9 2f 61 |.0..w*...SMG@./a| +000004c0 9c 41 c4 05 45 42 5e 42 d5 5e 30 95 30 4e a1 77 |.A..EB^B.^0.0N.w| +000004d0 79 b5 50 5c df d6 e7 74 42 d8 2b 66 02 fa 16 03 |y.P\...tB.+f....| 000004e0 03 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 a1 58 d5 1a a3 9f 85 4e b6 c8 b7 |.... .X.....N...| -00000040 cb c1 b0 cc 0a 80 59 1d 81 41 cc 4d 0b d3 bd 38 |......Y..A.M...8| -00000050 48 69 01 23 96 |Hi.#.| +00000030 16 03 03 00 20 93 c8 47 ed fd 9b 41 69 97 58 97 |.... ..G...Ai.X.| +00000040 cc 31 9c 93 a6 77 41 36 7a 90 f0 73 13 4a 7d 85 |.1...wA6z..s.J}.| +00000050 12 20 7d 91 fa |. }..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 83 ae fc 0d dd |.......... .....| -00000010 a1 3a 55 b0 2e 5e 21 9c 57 f3 1b 94 80 6c 0e bb |.:U..^!.W....l..| -00000020 78 ae f4 6c 20 d5 7e 23 11 1e 7d |x..l .~#..}| +00000000 14 03 03 00 01 01 16 03 03 00 20 16 00 35 d2 e0 |.......... ..5..| +00000010 ad f5 4c 10 98 fb 4f c7 81 1f 05 4b d6 7d 9c ac |..L...O....K.}..| +00000020 50 94 84 c8 35 80 ec 54 fc f3 ee |P...5..T...| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 d3 16 a3 f0 93 49 44 d4 82 60 35 |..........ID..`5| -00000010 e3 63 08 c0 4e 66 99 37 31 90 6c 15 03 03 00 12 |.c..Nf.71.l.....| -00000020 3c ea 2c 19 34 7b cc 6c 7a a9 15 31 6f 9c 3b b0 |<.,.4{.lz..1o.;.| -00000030 b2 1f |..| +00000000 17 03 03 00 16 83 e6 0f 3a ad c2 28 6c 82 ee 4a |........:..(l..J| +00000010 38 47 cc 86 75 70 e2 94 77 e6 6e 15 03 03 00 12 |8G..up..w.n.....| +00000020 13 c0 a0 4f 02 5e 6f 33 f6 ae d3 52 7d 72 72 a0 |...O.^o3...R}rr.| +00000030 1e 8d |..| diff --git a/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE b/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE index c851eb1a1f2..6f59dc6636b 100644 --- a/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE +++ b/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 f8 01 00 00 f4 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 12 01 00 01 0e 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,20 +7,22 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 79 00 0b 00 02 01 00 ff 01 00 01 00 00 |...y............| +00000080 01 00 00 93 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| -000000a0 00 0a 00 04 00 02 00 1d 00 0d 00 1a 00 18 08 04 |................| +000000a0 00 0a 00 04 00 02 00 1d 00 0d 00 16 00 14 08 04 |................| 000000b0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| -000000c0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| -000000d0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| -000000e0 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| -000000f0 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| +000000c0 06 03 00 32 00 1a 00 18 08 04 04 03 08 07 08 05 |...2............| +000000d0 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 |................| +000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| +000000f0 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 |&.$... /.}.G.bC.| +00000100 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +00000110 90 99 5f 58 cb 3b 74 |.._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 5d 02 00 00 59 03 03 e0 da ea 5e 09 |....]...Y.....^.| -00000010 bb 30 4c 10 db 85 36 44 38 9e a4 83 74 5f 2f 94 |.0L...6D8...t_/.| -00000020 a1 b4 45 61 73 2f 88 b3 ac ad e4 20 45 55 20 90 |..Eas/..... EU .| -00000030 b0 b0 d4 70 e6 10 13 5c f4 49 0e 9c 2a 52 5c 84 |...p...\.I..*R\.| -00000040 b2 55 1a ea e3 4b 5a 9f ac e9 7b 37 c0 2f 00 00 |.U...KZ...{7./..| +00000000 16 03 03 00 5d 02 00 00 59 03 03 64 5a cc e0 63 |....]...Y..dZ..c| +00000010 02 82 64 75 5e 2c b3 5f 23 c6 98 c8 95 07 40 00 |..du^,._#.....@.| +00000020 3e ef fd f6 00 af 81 0c 3a 47 a0 20 a1 fc 21 83 |>.......:G. ..!.| +00000030 cf 2b 34 5e b7 7b bd ec bb 8f 26 6a f2 26 7f 8f |.+4^.{....&j.&..| +00000040 51 13 6f ba 0d 1a f5 b7 1c 9d 6d 91 c0 2f 00 00 |Q.o.......m../..| 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 00000060 00 00 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 |......Y...U..R..| 00000070 4f 30 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 |O0..K0..........| @@ -60,33 +62,33 @@ 00000290 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 |s..Cw.......@.a.| 000002a0 4c 72 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 |Lr+...F..M...>..| 000002b0 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 |.B...=.`.\!.;...| -000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 ca 07 6e |............ ..n| -000002d0 67 12 8e f7 b4 55 c0 d4 88 73 35 f0 f1 ae c4 34 |g....U...s5....4| -000002e0 59 dc 05 df 75 96 54 f1 4f 7f 79 93 25 08 04 00 |Y...u.T.O.y.%...| -000002f0 80 d2 1d 65 15 23 74 e4 57 80 58 62 b5 6d ab 06 |...e.#t.W.Xb.m..| -00000300 11 4c e0 a0 7b 7e b5 78 87 47 71 30 c3 d8 86 b2 |.L..{~.x.Gq0....| -00000310 af 34 24 95 9c 2f 74 bb 6e c8 2a 8e 81 f8 fb d7 |.4$../t.n.*.....| -00000320 06 06 dc e8 95 01 65 fe 5d cb 9e 7f 36 9b 29 40 |......e.]...6.)@| -00000330 09 81 1b df 24 66 13 94 51 2a 48 31 e3 cb 3a 06 |....$f..Q*H1..:.| -00000340 c9 9c f4 36 b8 c0 de c1 3e 5e 79 95 f8 11 4b d8 |...6....>^y...K.| -00000350 0a b1 6c ef f4 ce 89 ba df ad 24 3d 7c 48 aa 70 |..l.......$=|H.p| -00000360 d8 0e 52 a8 12 1c 6b eb 5b c9 c3 a3 fa f0 60 d4 |..R...k.[.....`.| -00000370 54 16 03 03 00 04 0e 00 00 00 |T.........| +000002c0 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 15 d1 98 |............ ...| +000002d0 53 f4 98 b6 58 a5 cd 89 bb 32 21 83 4a e5 ad ba |S...X....2!.J...| +000002e0 1f ba db d0 4c c5 a3 89 0e 96 9f 59 60 08 04 00 |....L......Y`...| +000002f0 80 4e 14 a0 a7 33 e8 47 d5 7d 01 26 19 ff 1d 3c |.N...3.G.}.&...<| +00000300 2a f9 77 58 84 c0 07 b7 dc cc 82 85 a6 18 e9 33 |*.wX...........3| +00000310 70 15 04 75 bb 59 59 9c fa c0 cd b4 b7 f8 a3 0e |p..u.YY.........| +00000320 21 cd ac 7d 18 d2 34 e5 a9 c7 a1 5d 86 f3 74 2b |!..}..4....]..t+| +00000330 9b b0 21 5f cb 91 7f a0 d8 78 f0 7c 56 e3 69 ec |..!_.....x.|V.i.| +00000340 43 55 80 3f 02 d7 e0 10 52 15 4d 1b bc 2c 7f b7 |CU.?....R.M..,..| +00000350 86 cd 07 5d b9 f1 21 7e 18 da fc f8 45 45 cf 39 |...]..!~....EE.9| +00000360 62 3e c8 f1 6c 75 f4 fb fe f8 23 89 6a 0d b5 2e |b>..lu....#.j...| +00000370 4d 16 03 03 00 04 0e 00 00 00 |M.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 21 27 7f |....(........!'.| -00000040 32 c6 19 c4 a9 13 bf 5e 4b 53 5f c3 47 64 bb f8 |2......^KS_.Gd..| -00000050 21 d5 10 12 12 60 5e d8 e8 cf 1e fe 18 |!....`^......| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 e3 a2 01 |....(...........| +00000040 72 d5 55 57 f7 1a da 10 9a 04 7d 33 f4 18 b1 9a |r.UW......}3....| +00000050 09 38 45 dd 74 13 21 70 52 9c cc c2 3f |.8E.t.!pR...?| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 af e6 ee d0 75 |..........(....u| -00000010 df 97 22 b0 ff 46 8e 51 bb 23 70 8d 4a 22 01 b6 |.."..F.Q.#p.J"..| -00000020 13 34 68 fd 69 fe 0a 0f df 0e e6 41 48 49 8c e7 |.4h.i......AHI..| -00000030 d3 21 13 |.!.| +00000000 14 03 03 00 01 01 16 03 03 00 28 86 a1 0b 2b ef |..........(...+.| +00000010 13 8d 20 82 ad 17 92 64 0b 44 21 0f f0 dd 20 43 |.. ....d.D!... C| +00000020 4c db 92 3c 25 3a 12 ca 27 56 86 16 ca 9f ba 46 |L..<%:..'V.....F| +00000030 dc 96 86 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 10 16 77 |...............w| -00000010 99 da 71 ef 78 16 d7 cd 2c 7b 71 ba 8a 74 c1 65 |..q.x...,{q..t.e| -00000020 f2 f6 be 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| -00000030 72 d4 4a f6 6d 63 4c ad 02 46 36 18 61 47 61 7d |r.J.mcL..F6.aGa}| -00000040 50 08 |P.| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 20 7c 62 |............. |b| +00000010 05 52 7a 91 a7 13 96 96 29 11 1b 1a fe fa ad 7f |.Rz.....).......| +00000020 d2 3a 26 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.:&.............| +00000030 c7 2b 60 1b 9c 6b cb 22 08 f1 e3 c0 44 ab 70 21 |.+`..k."....D.p!| +00000040 68 48 |hH| diff --git a/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 b/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 index 6c7c3d47119..3673b8da393 100644 --- a/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 +++ b/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,85 +7,86 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 63 fa e1 78 d5 |....z...v..c..x.| -00000010 53 77 64 44 97 45 79 94 e7 79 dd da 70 81 46 66 |SwdD.Ey..y..p.Ff| -00000020 ac 7c 77 a2 f9 29 ca 48 e6 53 56 20 00 00 00 00 |.|w..).H.SV ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 07 aa 6b aa b6 |....z...v....k..| +00000010 ef a5 5c 62 d7 05 bb f8 9d ea 03 34 13 bf 00 1f |..\b.......4....| +00000020 e6 95 7b ef a5 2b ad e8 20 2f 21 20 00 00 00 00 |..{..+.. /! ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 36 |..+.....3.$... 6| -00000060 e2 c3 a0 14 f4 9c 50 9c 08 03 5e c2 b8 4b 66 85 |......P...^..Kf.| -00000070 71 fb bb 20 6e 97 3a f6 74 be 02 31 29 8e 18 14 |q.. n.:.t..1)...| -00000080 03 03 00 01 01 17 03 03 00 17 00 79 2a 2d 44 f4 |...........y*-D.| -00000090 12 2d 7c d6 8c 7a 27 76 a5 3a 6b c1 2d 40 8f 20 |.-|..z'v.:k.-@. | -000000a0 8b 17 03 03 02 6d 6e 16 f8 0f d2 67 3b e8 1a 95 |.....mn....g;...| -000000b0 2a ce 16 7b 95 21 7e 03 65 bf 01 ce e9 43 83 f6 |*..{.!~.e....C..| -000000c0 0e a9 d2 f2 d1 a3 2f d4 55 d2 27 83 44 3d f9 72 |....../.U.'.D=.r| -000000d0 00 8d 41 44 eb 93 ca 68 09 d1 bd f3 1a cc a0 53 |..AD...h.......S| -000000e0 a7 18 6e b7 27 d0 f5 e1 08 d8 9f 7b 37 bc 8f b9 |..n.'......{7...| -000000f0 84 6d e0 20 cf 99 bf c1 67 c8 00 74 4c 76 3e 2d |.m. ....g..tLv>-| -00000100 63 48 11 f1 75 30 ab a5 5b a2 cb 13 e9 e0 65 36 |cH..u0..[.....e6| -00000110 86 ce 8b 64 f6 dc e1 b7 0d 16 96 d1 ec 4b 93 d5 |...d.........K..| -00000120 6c 10 0d b7 d8 a2 45 b2 f0 e0 aa ab ab 11 8d d0 |l.....E.........| -00000130 2c fc 20 35 99 1b d6 3b 72 6d 88 03 80 5c 59 d4 |,. 5...;rm...\Y.| -00000140 04 18 ee 7a ed fe fb 52 c1 3c 93 95 e2 00 23 0d |...z...R.<....#.| -00000150 cc c1 4e 0a fb 55 33 93 9f c8 31 33 29 f5 12 3e |..N..U3...13)..>| -00000160 39 62 62 27 05 cf d2 be bd 7d 42 51 97 4f 71 95 |9bb'.....}BQ.Oq.| -00000170 10 f8 eb 0f d8 d1 69 aa 22 13 a8 fe 24 f6 87 a1 |......i."...$...| -00000180 9d ca cb 8f 99 39 2b fb 99 d9 18 8a fa fa 25 20 |.....9+.......% | -00000190 df 6a b3 d1 ac ce 56 8b 76 5d a9 46 1c 0b c7 57 |.j....V.v].F...W| -000001a0 90 02 10 55 85 49 48 89 d8 d6 4b 68 29 cb 28 66 |...U.IH...Kh).(f| -000001b0 1c d1 97 e6 a0 10 90 63 83 96 33 ee 5a 5a 5b 66 |.......c..3.ZZ[f| -000001c0 ca b3 0d be 6d 70 c5 de fd 78 c8 f8 e1 c5 78 ef |....mp...x....x.| -000001d0 07 2e 60 06 28 86 ed e6 bd 7b 37 33 0e 06 5e 06 |..`.(....{73..^.| -000001e0 fb 44 2b 96 16 fe 09 30 dc 03 53 bc c9 f9 6f 1e |.D+....0..S...o.| -000001f0 4b 79 a9 ac fe 20 3f 12 58 48 0c 40 a5 2f f2 6a |Ky... ?.XH.@./.j| -00000200 ea 44 69 93 54 4f 4d 6c 98 85 b1 c5 6f 50 83 b8 |.Di.TOMl....oP..| -00000210 8a 20 e3 b9 da b7 7d e4 ec 33 28 96 29 d7 dc a3 |. ....}..3(.)...| -00000220 d0 54 76 cd a6 99 17 e8 0f 14 d2 7c 4b 68 0a 80 |.Tv........|Kh..| -00000230 4f 0b 2b b5 16 68 dc 25 42 b5 0b f7 13 6a c5 81 |O.+..h.%B....j..| -00000240 c0 18 bc fb 40 86 cc 99 2e 70 2b 9a 72 eb be 57 |....@....p+.r..W| -00000250 a0 43 92 83 3b 7e c8 02 43 ab 17 7a 73 87 1a a2 |.C..;~..C..zs...| -00000260 1c 01 db b4 31 b1 d9 44 f1 c0 d9 de 27 bd 4c 8b |....1..D....'.L.| -00000270 1c f5 3d db d6 aa 98 7d 43 fe dd 64 85 8b c1 88 |..=....}C..d....| -00000280 a9 1e f1 04 0b 5d 3b c2 fd 3f b2 27 a7 28 d1 82 |.....];..?.'.(..| -00000290 13 fb 85 46 77 78 50 45 1b 4b c0 75 f2 32 8a 6d |...FwxPE.K.u.2.m| -000002a0 52 37 2e b1 80 e9 81 3b 60 c8 88 78 11 3f 0f 96 |R7.....;`..x.?..| -000002b0 d1 4b 19 49 91 b5 70 44 2d 62 a1 04 8f 98 89 ab |.K.I..pD-b......| -000002c0 75 1f 8a 97 d5 28 dc 88 20 92 7f f2 90 16 1b de |u....(.. .......| -000002d0 54 7c 5f 05 8f c9 70 a1 f5 8c 99 09 43 ab 09 73 |T|_...p.....C..s| -000002e0 dd 5e 62 c3 9f c8 e1 fa 9e 98 65 18 b5 5e 4e f9 |.^b.......e..^N.| -000002f0 85 a4 cc dc b8 12 1b eb 0a bc bc bd 1c 2f 51 0e |............./Q.| -00000300 8f 55 f1 10 22 06 ca cb f2 97 54 63 1c 98 36 9f |.U..".....Tc..6.| -00000310 1d 66 b0 17 03 03 00 99 f0 14 4d 69 84 b3 ca d4 |.f........Mi....| -00000320 96 9c e2 3c a4 55 f4 b6 01 1f 1e 1f 77 98 c4 84 |...<.U......w...| -00000330 5e ce 4c 0b bf ba 39 6b 36 a6 15 9c d1 90 87 d1 |^.L...9k6.......| -00000340 13 39 1c dd 86 0f a0 06 f7 fc f7 c9 10 4e 46 0a |.9...........NF.| -00000350 03 12 a0 bf 3e f3 7d e6 1b b7 ce ec 16 84 52 8e |....>.}.......R.| -00000360 bc 9c 9a 4f 2f a7 d9 aa f3 d6 be 0a f8 39 2d 18 |...O/........9-.| -00000370 28 9e 35 6e 25 25 46 9b 49 61 a6 ee 6a 87 d2 5f |(.5n%%F.Ia..j.._| -00000380 54 e6 fb 96 a3 e9 8a 05 c2 fb 71 0b d7 13 2e 19 |T.........q.....| -00000390 e5 5c a2 d0 f4 b3 34 95 e1 1d 24 ef 33 a2 0a d5 |.\....4...$.3...| -000003a0 65 b2 5f 46 73 45 33 69 d6 c3 f6 49 20 e2 00 bd |e._FsE3i...I ...| -000003b0 16 17 03 03 00 35 89 2f 34 08 44 35 6a 52 1a fd |.....5./4.D5jR..| -000003c0 e4 be 2b 0e 0a dd 2d c1 e7 e3 20 7a 0a 3e 87 1d |..+...-... z.>..| -000003d0 2b 64 87 c5 11 54 46 1a 5c 89 e2 97 3f 83 b2 b4 |+d...TF.\...?...| -000003e0 04 ed d2 c4 1d 3d 37 1f e1 62 f2 |.....=7..b.| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 53 |..+.....3.$... S| +00000060 3c 5e 7d 61 39 39 6c f7 ea 14 d3 f0 40 23 30 8b |<^}a99l.....@#0.| +00000070 7e 1f 41 86 f8 2e 12 0a f5 67 13 28 46 6f 14 14 |~.A......g.(Fo..| +00000080 03 03 00 01 01 17 03 03 00 17 a8 64 4a 9d f1 a0 |...........dJ...| +00000090 3c 1b e3 20 a2 66 80 7f 13 b5 a9 f0 8f ee 5b 4b |<.. .f........[K| +000000a0 af 17 03 03 02 6d 26 d2 8f df b4 d5 d3 9a c8 92 |.....m&.........| +000000b0 4c 32 63 80 6b 5f 99 11 0f 4b be 14 77 55 86 d1 |L2c.k_...K..wU..| +000000c0 27 94 18 50 27 1c 84 9c 38 03 fb 11 d3 5a ea 64 |'..P'...8....Z.d| +000000d0 d1 15 47 1d fc cc 6e bf 5e 4d 45 74 f2 ca 44 77 |..G...n.^MEt..Dw| +000000e0 32 6d 02 3a 9f 44 aa 5c 5d 62 64 ee 44 0d 45 05 |2m.:.D.\]bd.D.E.| +000000f0 de 40 d0 83 c9 b3 21 39 a0 8f 5b 5a e1 96 2f 0b |.@....!9..[Z../.| +00000100 4b 12 da a7 dc 7b 2a 73 14 7f cc 93 fd a8 47 1c |K....{*s......G.| +00000110 f7 88 76 5d 30 29 af 65 ac 52 25 04 13 be 96 92 |..v]0).e.R%.....| +00000120 bb e4 86 a0 b7 c8 67 63 ef cb 1f 78 7e bf 3c 5f |......gc...x~.<_| +00000130 7a a6 89 4a 94 f3 2e 01 8b b9 81 21 57 00 5e 26 |z..J.......!W.^&| +00000140 22 9b eb e0 73 87 cd 77 46 d4 c8 1d 0a 4f d8 83 |"...s..wF....O..| +00000150 0b 0a 43 3f 37 53 e2 0a 4b bb ef e8 8d 2a dc 51 |..C?7S..K....*.Q| +00000160 b0 b9 90 7e 1a c5 31 e0 1b 0f 0c 7e 96 7b aa 49 |...~..1....~.{.I| +00000170 ad 84 b0 0a 75 d6 37 58 bd 7f f6 ac 50 c5 d7 93 |....u.7X....P...| +00000180 70 ce b1 cd 00 7c 79 1a e5 ec 04 7b 12 8f fb 80 |p....|y....{....| +00000190 54 d0 2b a0 9e 83 0d 05 a7 f5 4b e8 b4 36 1c d0 |T.+.......K..6..| +000001a0 88 34 a6 71 51 d6 cf 59 c9 ad 03 d8 38 f2 15 f0 |.4.qQ..Y....8...| +000001b0 63 9d 34 a3 f4 bc de 8f ae 26 97 c0 98 8e 59 4e |c.4......&....YN| +000001c0 1f 74 a1 d4 2c 1a 18 20 ef e8 06 58 74 dd ed 40 |.t..,.. ...Xt..@| +000001d0 50 dd 8b a4 77 15 1b 9e 63 7e c7 11 63 1a a9 d5 |P...w...c~..c...| +000001e0 16 c2 8f f5 6c ce cd 03 e6 2d cc da 75 1a ce cb |....l....-..u...| +000001f0 ea 41 de dd 59 e5 68 90 98 69 76 a3 d0 d4 ed d1 |.A..Y.h..iv.....| +00000200 e9 9a cd b8 29 73 eb 9c e6 6f ee 8d 91 84 9e 2e |....)s...o......| +00000210 b9 23 2b 04 a0 f6 5f 0b 16 07 49 ae 6f 33 b0 ee |.#+..._...I.o3..| +00000220 be ff 75 52 da 7b 06 05 6c 8f 87 1f 48 2f fb 59 |..uR.{..l...H/.Y| +00000230 79 a6 99 cb a6 0b 73 fb 4c d0 cc eb ba 51 1a 6d |y.....s.L....Q.m| +00000240 9a 33 27 e3 f4 cf 16 bc c0 82 da 21 04 4a 7b e0 |.3'........!.J{.| +00000250 12 a5 5e de 22 d2 df b4 c4 c9 fa 11 97 7b 07 ea |..^."........{..| +00000260 11 c8 2c 55 b8 6d c2 64 6d fa e0 6f b8 5c 50 ae |..,U.m.dm..o.\P.| +00000270 a6 2e aa bf 2f 2a 74 2d 1c 11 c2 44 d7 28 b8 5e |..../*t-...D.(.^| +00000280 6a 2d bc 0d 2e a7 a2 b6 b6 ae 12 2c a2 c4 ba 5c |j-.........,...\| +00000290 0b 3f 17 2e 98 30 ce 6c 8e 88 3c f9 a8 e1 68 8d |.?...0.l..<...h.| +000002a0 52 c8 a1 b3 3f 12 e1 35 f0 eb ee 9f 0d bb 3c 90 |R...?..5......<.| +000002b0 2c e2 2c 95 2e f3 e2 f6 f2 f1 be b8 03 02 84 69 |,.,............i| +000002c0 56 8f 3b 1d 68 77 f1 52 eb 48 4f e8 c8 5b 0a df |V.;.hw.R.HO..[..| +000002d0 a1 74 1e e1 47 a2 9a 9a 83 6d c2 ea f3 1b fc 8f |.t..G....m......| +000002e0 b6 aa 18 7e 85 46 ff 33 0b 6e 1f 5b f1 70 c0 45 |...~.F.3.n.[.p.E| +000002f0 f6 bb a0 da 74 e0 9a 3c a7 e2 07 ef 0b e5 9a 5b |....t..<.......[| +00000300 6e 9b aa 6c a4 97 84 5d 77 f5 33 b8 e3 45 c0 00 |n..l...]w.3..E..| +00000310 21 c7 91 17 03 03 00 99 ee bf d2 9c 82 9f 68 b4 |!.............h.| +00000320 5e 15 09 1a 7a c1 f9 72 ff ca 0e d9 f1 9f 7f 8c |^...z..r........| +00000330 dc 4a 8d d3 37 7b 81 42 ef 9b 2b 5f 9a 4b 40 8e |.J..7{.B..+_.K@.| +00000340 6b 24 53 79 32 b0 d1 24 2a 6f c9 fb a8 82 c1 01 |k$Sy2..$*o......| +00000350 1e 0b 11 7f 85 c7 ee d4 29 12 08 99 8f 00 ef af |........).......| +00000360 2c 5d c5 b1 25 a3 a9 f0 f1 a3 2b f8 7f e6 31 1b |,]..%.....+...1.| +00000370 51 20 af 3f a7 4e 5c 3d 73 21 04 0f 2c 5c cd f3 |Q .?.N\=s!..,\..| +00000380 eb d1 01 ef b0 e3 64 f7 33 d3 05 82 9f a6 71 3b |......d.3.....q;| +00000390 b2 ab 08 61 57 ad 74 d1 e2 8f 2c c9 73 c3 e0 ac |...aW.t...,.s...| +000003a0 ed 18 4b 70 0d 9a bf ae b4 db 07 7d 25 3e 7f 3d |..Kp.......}%>.=| +000003b0 14 17 03 03 00 35 db be d2 61 e1 3f a3 0b fe 39 |.....5...a.?...9| +000003c0 b2 86 42 72 a6 ee 02 90 c2 d1 d1 5c 3d 61 c8 28 |..Br.......\=a.(| +000003d0 28 7c 01 40 26 f1 e1 f1 81 50 03 4c 6c 32 6d 8b |(|.@&....P.Ll2m.| +000003e0 dd 60 cf fc a9 3c fe e1 4d d0 d2 |.`...<..M..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 07 8e f6 0b 41 |..........5....A| -00000010 be 74 45 99 5e 35 59 4f 2e 59 d4 37 77 ca 53 d4 |.tE.^5YO.Y.7w.S.| -00000020 fd 33 bf dc 65 85 ee ad c5 d6 94 7e 6e e8 02 cf |.3..e......~n...| -00000030 15 d2 04 cb e1 9f 5e 94 dd 5f 37 17 95 17 0c b7 |......^.._7.....| -00000040 17 03 03 00 17 1f aa e9 7d 34 dc 12 da 3b cb dd |........}4...;..| -00000050 1c d3 b0 f1 79 ad cc 66 06 64 69 21 17 03 03 00 |....y..f.di!....| -00000060 13 b7 c7 a2 01 48 27 3a 44 e6 c6 47 a9 19 5f d2 |.....H':D..G.._.| -00000070 f8 96 98 70 |...p| +00000000 14 03 03 00 01 01 17 03 03 00 35 bd 1e ca 07 84 |..........5.....| +00000010 c8 ba 87 6d d3 ed 53 20 79 76 34 af 30 e6 bf c5 |...m..S yv4.0...| +00000020 74 a0 d0 b3 13 17 a9 3c c7 b3 47 5b e7 b4 6d 18 |t......<..G[..m.| +00000030 e5 3f 12 5c ca c9 26 87 c4 96 c4 9b 45 23 7f f7 |.?.\..&.....E#..| +00000040 17 03 03 00 17 28 0b 72 a0 6e ac 55 ec c0 b7 21 |.....(.r.n.U...!| +00000050 3f 7a 16 98 40 76 7d 3c 95 24 98 3b 17 03 03 00 |?z..@v}<.$.;....| +00000060 13 8e 23 e0 33 31 dc 39 fb 54 a6 a2 63 36 e4 2a |..#.31.9.T..c6.*| +00000070 5a 1c bc 09 |Z...| diff --git a/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 b/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 index c5bac350a6e..5fcaba0d4fd 100644 --- a/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 +++ b/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,87 +7,88 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 3d 39 60 81 a4 |....z...v..=9`..| -00000010 cc 92 5d fd 8b 21 58 da 2e 4c e2 70 2b 12 d2 8c |..]..!X..L.p+...| -00000020 35 55 bc ba 79 c1 9e 6f 78 8c cf 20 00 00 00 00 |5U..y..ox.. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 76 2d 81 0b a9 |....z...v..v-...| +00000010 70 b7 fe 52 ef d3 80 c4 1d bf f7 19 99 3c 4c aa |p..R.........4.3I8..| -000002a0 d1 04 b4 13 a8 5f 0b f2 41 77 d4 c8 b2 d3 0e d6 |....._..Aw......| -000002b0 8c dc 34 ad 2a d9 4b 5f 4a e2 17 0a be 2a 55 4a |..4.*.K_J....*UJ| -000002c0 44 a7 b0 0f d1 39 b0 e5 9d 77 6b d7 44 15 99 bf |D....9...wk.D...| -000002d0 c8 02 57 90 5b 73 29 fe ab 85 93 c3 dc 1c b0 b2 |..W.[s).........| -000002e0 14 78 01 99 f5 d2 db ef ae 0e 2a d9 17 1e 70 fa |.x........*...p.| -000002f0 bb 74 fe 93 a0 aa ff 79 cd 8b 6d 3d 79 66 d2 c8 |.t.....y..m=yf..| -00000300 90 c7 2c e6 54 26 de f7 4d b8 a7 73 cd 92 fc 42 |..,.T&..M..s...B| -00000310 ad 4e ff 17 03 03 00 99 c6 07 36 ce 58 9c fe 38 |.N........6.X..8| -00000320 aa b4 5c c8 8e f5 11 19 82 4c 4b 2b 0a 08 be 3f |..\......LK+...?| -00000330 11 76 06 4b d3 1b b7 fc 66 d9 db de fb 6a ee 29 |.v.K....f....j.)| -00000340 f6 a5 4b 96 f3 3c a0 67 44 73 d4 46 c5 d4 a1 f8 |..K..<.gDs.F....| -00000350 71 36 7c a5 62 79 fc be f9 34 55 85 31 8f fc e3 |q6|.by...4U.1...| -00000360 46 be 64 1e 2d 1b 21 c3 89 8e 1c cc df 30 05 57 |F.d.-.!......0.W| -00000370 2e d5 d5 67 11 10 46 1a af 99 01 0e fd 40 53 1f |...g..F......@S.| -00000380 b0 f0 76 3e 8e c1 7a 6a fe fe ef c1 08 6e ea 9b |..v>..zj.....n..| -00000390 75 6c 62 86 07 50 ee 1f ef 3b 55 fd 68 44 47 27 |ulb..P...;U.hDG'| -000003a0 07 c1 53 b5 13 c5 e0 a4 d6 9e 8a 3c 78 a0 04 b7 |..S............|.I+NU.t..| +00000130 23 32 9d aa b1 17 15 3d 37 85 42 0e 5f 7c fa 5b |#2.....=7.B._|.[| +00000140 b8 ae f3 b9 4d b2 40 b5 e2 de e2 b3 f0 27 a6 f2 |....M.@......'..| +00000150 0c 28 4b 77 ee 38 dc ec 17 28 18 03 13 85 60 2c |.(Kw.8...(....`,| +00000160 ab 16 e1 1c c6 e1 91 e0 5f f3 b6 f7 1c 3b 5f 03 |........_....;_.| +00000170 6a d5 b0 a0 5b ab 6d 9c b2 ee 8e 50 49 94 7d db |j...[.m....PI.}.| +00000180 3b fe 68 e2 79 3e 2d 33 06 a6 b2 9c 8b 7d 93 04 |;.h.y>-3.....}..| +00000190 b4 9e 07 6d 15 80 63 38 8e 4b c5 e6 88 a0 6a f2 |...m..c8.K....j.| +000001a0 11 60 11 7a f7 6e 7e 47 9f fd 77 12 c9 d5 8e 58 |.`.z.n~G..w....X| +000001b0 84 51 2c f6 fd 2b d1 dc a6 51 d8 20 3f 06 76 ad |.Q,..+...Q. ?.v.| +000001c0 dd 37 b6 e9 86 4e cb 31 76 79 60 26 c7 b4 d5 67 |.7...N.1vy`&...g| +000001d0 2c 70 22 f4 4d b5 60 61 41 48 65 a8 d0 b5 d8 47 |,p".M.`aAHe....G| +000001e0 08 bf 5b 67 e8 99 c4 a5 91 1e 36 6b 37 53 7b 65 |..[g......6k7S{e| +000001f0 ac af 2d df 8e 77 e2 46 1a 65 45 0a 00 f2 8f 9d |..-..w.F.eE.....| +00000200 47 1c 93 64 52 c3 d9 91 47 41 88 7f 81 ea 8f 2b |G..dR...GA.....+| +00000210 a9 fa 4b d5 9d 6f 30 36 dc af e0 96 b3 f0 e4 6a |..K..o06.......j| +00000220 a3 10 cf 0e 53 64 e3 18 52 08 a9 16 e3 6d e9 0a |....Sd..R....m..| +00000230 ec 4d a4 f7 f1 ee 38 28 88 31 aa 38 a7 14 09 f4 |.M....8(.1.8....| +00000240 1a 31 ac 40 46 dd f2 4f 7f ff f4 fc 71 42 61 73 |.1.@F..O....qBas| +00000250 03 47 9f ec 69 7f 77 e3 91 29 cd 89 7f 45 6b 9d |.G..i.w..)...Ek.| +00000260 f5 33 66 8b 74 bc 53 ff 54 c3 af 48 8e d8 25 0a |.3f.t.S.T..H..%.| +00000270 99 49 08 29 f3 b2 a5 d0 5b ca 89 e2 d7 f5 5f 40 |.I.)....[....._@| +00000280 72 6f b4 d6 20 39 79 4a 0e 7c 00 60 68 eb 1e ab |ro.. 9yJ.|.`h...| +00000290 ee 38 35 f2 db 83 9c 0b 52 80 15 14 ae 6b dc f5 |.85.....R....k..| +000002a0 d5 f3 83 cb e7 5f 5c 98 e2 f2 d0 52 68 92 ff f6 |....._\....Rh...| +000002b0 7a ce ff ae 96 6e ad 11 d2 5e bc 60 16 55 cd 81 |z....n...^.`.U..| +000002c0 25 67 5b db 76 59 36 a8 48 d6 91 86 4f cb 87 5f |%g[.vY6.H...O.._| +000002d0 ea 96 e4 71 df ac 54 5a a0 e1 0a bd 88 68 ff 0a |...q..TZ.....h..| +000002e0 97 be 9b da cf aa e1 b1 74 c9 8d 5f 19 f5 df 53 |........t.._...S| +000002f0 a0 57 93 7d c3 fe 37 78 2a ba 6b c2 a1 51 41 f4 |.W.}..7x*.k..QA.| +00000300 ee 57 ed d2 7d 48 14 31 4a f7 14 d4 0e 42 9e fb |.W..}H.1J....B..| +00000310 fb f4 cd 17 03 03 00 99 6b 70 ae fc d3 07 5e 7f |........kp....^.| +00000320 39 2a 27 34 54 8a b6 4d 39 36 d4 38 0c ed 8c 24 |9*'4T..M96.8...$| +00000330 fc 29 1d 59 74 99 f1 e1 a1 23 4b 6d 27 31 f4 2d |.).Yt....#Km'1.-| +00000340 8b b3 23 aa 92 5f 01 3d a1 f6 b5 24 8e 56 ea eb |..#.._.=...$.V..| +00000350 4e 0a dc 23 ae 32 1b 0d cb bc 60 87 b7 35 32 5f |N..#.2....`..52_| +00000360 10 32 fb 89 32 3f 99 0e 30 0d 65 28 69 c4 3b f8 |.2..2?..0.e(i.;.| +00000370 6c 04 a5 bf ec e9 aa c4 bc b4 55 e2 d0 09 a1 4b |l.........U....K| +00000380 82 f8 a5 37 ab ca 69 f4 bc 24 69 c4 ce 07 6c ee |...7..i..$i...l.| +00000390 d6 08 92 14 41 ca 8f c8 c9 37 ae b5 f3 29 ff 69 |....A....7...).i| +000003a0 7a 18 4e 93 dd eb 52 58 d2 6b 22 6d b6 29 70 b3 |z.N...RX.k"m.)p.| +000003b0 ea 17 03 03 00 45 10 35 86 2e d4 e3 92 35 a3 0e |.....E.5.....5..| +000003c0 a1 cd 79 11 05 cd 77 c4 93 f4 6a ba f8 fc 4b bd |..y...w...j...K.| +000003d0 63 5d c0 2d a0 c9 c2 2a 10 79 e9 0c bc 0b 18 c1 |c].-...*.y......| +000003e0 15 18 c0 8a d7 05 39 f1 de 6e 8e cb dd 73 5f ee |......9..n...s_.| +000003f0 28 93 f9 92 35 56 1f c1 e4 8d 89 |(...5V.....| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 45 ee 00 18 db 1e |..........E.....| -00000010 67 aa 0f 9e 5c 20 7d 25 27 49 e8 d5 60 02 78 7b |g...\ }%'I..`.x{| -00000020 23 58 70 67 67 93 ca 4d 50 69 b1 cf d9 dc 31 d3 |#Xpgg..MPi....1.| -00000030 03 36 b0 07 39 59 52 e1 c7 36 6d 16 0b 56 03 c6 |.6..9YR..6m..V..| -00000040 a0 ec 0e 6b ed de 7b ba 51 96 83 b6 b8 77 8f 6a |...k..{.Q....w.j| -00000050 17 03 03 00 17 77 f6 6f 83 00 ad eb be 16 26 3d |.....w.o......&=| -00000060 27 e8 58 73 a2 bc 11 ff 14 54 4a 15 17 03 03 00 |'.Xs.....TJ.....| -00000070 13 bc 94 3f 6e ee 1b 40 b0 2e 03 13 47 28 38 4d |...?n..@....G(8M| -00000080 2d 26 5d 15 |-&].| +00000000 14 03 03 00 01 01 17 03 03 00 45 2f 08 54 f6 2b |..........E/.T.+| +00000010 fd 13 5d 87 d3 b6 73 5e 20 88 af 53 db 7e 3c 37 |..]...s^ ..S.~<7| +00000020 1d 52 a4 ae 91 3f 24 a7 30 26 02 da 13 f3 c5 60 |.R...?$.0&.....`| +00000030 28 e6 eb 8f e1 1b 58 2d bb d0 06 c4 67 33 1c a1 |(.....X-....g3..| +00000040 03 cb 16 56 1b 91 06 08 b6 34 c5 de 97 04 ee f0 |...V.....4......| +00000050 17 03 03 00 17 6c 7e 3d 5d 98 4e 42 81 42 c5 2c |.....l~=].NB.B.,| +00000060 b2 c2 d3 c9 58 bc 13 bc 61 cd 63 f2 17 03 03 00 |....X...a.c.....| +00000070 13 83 c7 4a b6 10 69 b4 16 be 25 a1 db cb c9 94 |...J..i...%.....| +00000080 8f a2 27 22 |..'"| diff --git a/crypto/tls/testdata/Client-TLSv13-ALPN b/crypto/tls/testdata/Client-TLSv13-ALPN index f40340ac152..ff0989c567b 100644 --- a/crypto/tls/testdata/Client-TLSv13-ALPN +++ b/crypto/tls/testdata/Client-TLSv13-ALPN @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 01 12 01 00 01 0e 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 2c 01 00 01 28 03 03 00 00 00 00 00 |....,...(.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,87 +7,89 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 93 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 ad 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 10 00 10 |................| -000000d0 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |...proto2.proto1| -000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| -000000f0 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 |&.$... /.}.G.bC.| -00000100 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| -00000110 90 99 5f 58 cb 3b 74 |.._X.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 10 00 10 00 0e 06 70 72 6f |.............pro| +000000f0 74 6f 32 06 70 72 6f 74 6f 31 00 2b 00 09 08 03 |to2.proto1.+....| +00000100 04 03 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 |........3.&.$...| +00000110 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)| +00000120 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;| +00000130 74 |t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 c2 2e 95 0c cf |....z...v.......| -00000010 63 40 d8 a0 bd 51 27 e2 62 79 72 26 b1 d4 38 5b |c@...Q'.byr&..8[| -00000020 50 03 66 d2 2e 8e 46 b7 cf 40 0a 20 00 00 00 00 |P.f...F..@. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 bb 72 d9 b8 e5 |....z...v...r...| +00000010 0b 80 14 4c 16 9b 86 ec 26 62 f2 f9 00 85 a6 ae |...L....&b......| +00000020 44 f4 27 c4 13 67 4a 2e 96 e6 33 20 00 00 00 00 |D.'..gJ...3 ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 21 |..+.....3.$... !| -00000060 18 6f 64 73 17 22 b0 11 60 92 ab 01 b3 fb 8a 2d |.ods."..`......-| -00000070 27 15 5a 46 ec 6c c3 0c a7 73 00 b2 7e 9f 4f 14 |'.ZF.l...s..~.O.| -00000080 03 03 00 01 01 17 03 03 00 24 68 7f 90 b2 66 74 |.........$h...ft| -00000090 36 f5 fc 65 55 19 c1 78 65 d8 dc 46 fb ad b6 2c |6..eU..xe..F...,| -000000a0 89 f3 d1 fd 3e 46 c2 50 01 24 72 2a 64 98 17 03 |....>F.P.$r*d...| -000000b0 03 02 6d 40 bc da 1a 9c 8b d7 15 24 4f d4 c1 9c |..m@.......$O...| -000000c0 8b 3c 8b 51 37 41 46 a8 cb b4 9c 50 c0 be 72 ef |.<.Q7AF....P..r.| -000000d0 81 d3 7f ed ec 96 e2 c2 08 0e 7e 23 95 c3 4f 79 |..........~#..Oy| -000000e0 01 2d 26 81 c1 ba d0 58 61 d8 c5 b7 e7 79 4f 3e |.-&....Xa....yO>| -000000f0 d8 c1 07 ae de 6a 1e 78 eb 9d 8c a1 2a 57 9c 56 |.....j.x....*W.V| -00000100 1f 6c 6e bb 2d 70 6d 55 92 10 3f 39 7e 8a d2 30 |.ln.-pmU..?9~..0| -00000110 e5 1c 4b df c0 96 d0 de 16 09 c6 34 23 16 54 a8 |..K........4#.T.| -00000120 f5 0a 1a af 9a 27 60 89 19 6a 3e 69 12 de 76 4c |.....'`..j>i..vL| -00000130 88 f2 ca 6c 0b 94 b8 d2 bc 09 f0 d3 86 74 3c 3f |...l.........tq..| -00000290 5c 9a b7 6b f2 d0 1e 55 2c 1c ac 5d 21 64 a2 d2 |\..k...U,..]!d..| -000002a0 a9 dd a8 49 7c 22 26 8e ca 75 a3 ef 52 42 d0 38 |...I|"&..u..RB.8| -000002b0 f4 02 60 af ee 33 30 46 90 a5 b3 7a 66 c8 ab 10 |..`..30F...zf...| -000002c0 3f 76 d1 76 aa 5d da c4 29 ca d7 22 c4 44 b4 e8 |?v.v.]..)..".D..| -000002d0 64 b6 6d 0f 16 cd d9 e9 62 17 91 64 03 0f 99 8f |d.m.....b..d....| -000002e0 c6 97 c8 4b c9 45 c4 31 e4 1f a8 b0 aa 67 02 e7 |...K.E.1.....g..| -000002f0 20 68 2a 89 f9 b8 e8 ce 93 d0 a3 1b 0d d1 4c 45 | h*...........LE| -00000300 c2 19 ac aa 87 43 95 ae c4 56 56 fe 4b 0e af db |.....C...VV.K...| -00000310 08 6a 14 8e 8b 7e 64 9d 6d 6e 0f 78 7c e4 f8 51 |.j...~d.mn.x|..Q| -00000320 17 03 03 00 99 2d 7b fa e6 dc da 89 93 da 93 91 |.....-{.........| -00000330 9c 25 08 50 66 eb a7 e4 f1 20 da 33 e5 cd a5 89 |.%.Pf.... .3....| -00000340 00 a7 47 9c 84 e6 cf 6d e1 86 02 af fb 54 ff b3 |..G....m.....T..| -00000350 b5 a4 e1 46 1a 3a 89 ad f0 c4 63 fe d2 eb bb 6c |...F.:....c....l| -00000360 6e cc a9 95 b0 e4 df f8 44 46 16 43 07 d7 8e 6e |n.......DF.C...n| -00000370 9b ee 0b 22 7a 23 f4 b8 3e fd fe 99 13 9d 18 bc |..."z#..>.......| -00000380 77 99 2f 90 21 a1 5f cc 9f 08 e2 75 44 2f bf 58 |w./.!._....uD/.X| -00000390 70 f2 95 b2 13 20 f3 ed 51 de e8 02 c6 ca 44 57 |p.... ..Q.....DW| -000003a0 eb 0b 9f 3e 61 f1 1a 6e 6b 13 f5 14 f3 43 19 f6 |...>a..nk....C..| -000003b0 7d 46 3a 73 49 2f fd 83 c3 68 c7 ba b4 e8 17 03 |}F:sI/...h......| -000003c0 03 00 35 67 2b 2b 9b f0 f3 d9 09 c4 01 20 ea 22 |..5g++....... ."| -000003d0 c9 7c e6 7a ce 3f 7f 84 c2 1f 6e eb d6 ce 85 b8 |.|.z.?....n.....| -000003e0 2c 3c 9f 77 8b 37 11 dd 64 d1 ae ba 85 50 7e ba |,<.w.7..d....P~.| -000003f0 14 a9 05 ff 82 3b e5 7d |.....;.}| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 69 |..+.....3.$... i| +00000060 d7 31 51 9b e6 1d 98 09 9f 5f 6c 05 10 ba 64 b5 |.1Q......_l...d.| +00000070 b9 8f b8 c0 2a c1 7f 89 13 ed 04 38 e9 78 43 14 |....*......8.xC.| +00000080 03 03 00 01 01 17 03 03 00 24 99 f3 d5 db e2 35 |.........$.....5| +00000090 4b fb b2 05 e6 03 c2 f2 c4 ea 64 d2 e4 d3 17 e7 |K.........d.....| +000000a0 72 34 e8 b2 d6 61 91 3b b3 03 ea 1c 33 57 17 03 |r4...a.;....3W..| +000000b0 03 02 6d 22 da 71 90 42 da 0a 03 52 98 42 e3 71 |..m".q.B...R.B.q| +000000c0 db 57 e0 9d 70 89 4b 4c a9 a5 4d 39 02 19 f1 09 |.W..p.KL..M9....| +000000d0 5a 9c 33 c9 f2 8d 7e 78 c3 b3 ae 1b 2c 7b 73 ef |Z.3...~x....,{s.| +000000e0 3a ad d8 51 82 90 bc 6b 0d 6f a6 f0 46 8d 72 29 |:..Q...k.o..F.r)| +000000f0 ca 84 d8 b1 27 e3 8d 8f f5 ce f0 f0 d9 2f 9c 71 |....'......../.q| +00000100 b9 bc 89 af 92 18 d2 c9 07 b2 eb 94 40 42 d2 7a |............@B.z| +00000110 c8 be 49 35 b6 b7 f3 b9 64 c1 56 fe fc d8 11 04 |..I5....d.V.....| +00000120 6c d7 e9 18 98 29 eb d5 6f 59 0d fa 25 85 f7 3c |l....)..oY..%..<| +00000130 df 76 d9 52 10 72 59 d6 36 5b b0 54 01 1d ac 9e |.v.R.rY.6[.T....| +00000140 9b 86 5f 5b ee 18 74 ec 8e 8b da 0f df 71 50 e2 |.._[..t......qP.| +00000150 cd 58 98 23 a0 21 94 ac eb db 3a fe f6 8d aa cc |.X.#.!....:.....| +00000160 21 23 e6 35 f7 0e 42 0e 50 48 14 22 f3 83 91 3d |!#.5..B.PH."...=| +00000170 73 22 5b 74 e7 e8 d1 b5 ee cd 7e c3 ee 0d 13 a9 |s"[t......~.....| +00000180 aa ae 0b 12 b0 3a 9d 6f 01 68 27 e4 62 e0 0e 67 |.....:.o.h'.b..g| +00000190 e4 de 69 74 8d f1 7a 3b 16 bb 1d a0 ad bf c5 4b |..it..z;.......K| +000001a0 50 9e b0 dc 08 73 14 99 c9 ad de 04 df 75 09 de |P....s.......u..| +000001b0 e4 27 ec 2b 75 79 db 82 8c aa 42 af 40 df 32 0e |.'.+uy....B.@.2.| +000001c0 e6 1d 93 d1 00 f7 18 59 43 9c 03 6c f7 bf ac a2 |.......YC..l....| +000001d0 8b 10 be b1 a8 b6 4e 84 2b c0 ff 87 4d 26 c2 8f |......N.+...M&..| +000001e0 63 64 7a 66 a6 12 0b e4 06 9e ff af fe 03 55 c7 |cdzf..........U.| +000001f0 13 92 22 ec ed 89 76 2d 36 8a 4a 92 f1 a5 b6 ac |.."...v-6.J.....| +00000200 d4 19 46 9d f3 e0 52 6d 01 ee bf ab d5 17 c0 33 |..F...Rm.......3| +00000210 b5 81 e1 81 a2 e9 44 b7 20 0e f4 f0 35 bb d4 8d |......D. ...5...| +00000220 bc 83 fc 59 fb 1d 5e e0 c4 4c 9e cc c3 72 b7 3d |...Y..^..L...r.=| +00000230 01 a4 f2 df e2 a7 44 d1 f1 20 90 31 53 09 50 eb |......D.. .1S.P.| +00000240 80 85 23 52 68 7d b2 51 60 0c 00 87 c3 42 88 07 |..#Rh}.Q`....B..| +00000250 de 59 fd 3d 68 a3 22 50 cb 67 43 94 02 77 24 6a |.Y.=h."P.gC..w$j| +00000260 8d a4 4f 85 7f 19 a0 b5 10 76 2a 85 4c 84 12 e3 |..O......v*.L...| +00000270 f7 ce b8 30 9f d0 9f 8a 26 42 28 f4 cb f7 c4 c2 |...0....&B(.....| +00000280 aa 34 c2 72 64 dc 6d 9d d4 26 2f 14 4d 97 2c 00 |.4.rd.m..&/.M.,.| +00000290 2d 46 0f 07 9c 3d 76 d4 55 a7 15 13 b2 41 e3 f4 |-F...=v.U....A..| +000002a0 33 ae 1b 26 68 43 62 de c1 c2 61 26 08 1b 20 13 |3..&hCb...a&.. .| +000002b0 bc 58 72 c2 16 fe 4d 2e 68 8b 31 61 ac c9 55 c5 |.Xr...M.h.1a..U.| +000002c0 3c 5a 77 c2 61 47 4a d6 0d c4 8a bc bb 63 ca ea |0....8bA.L94..| +000003e0 ee 48 70 3c 23 65 90 cb f9 4f 76 72 dd f3 64 83 |.Hp<#e...Ovr..d.| +000003f0 23 38 79 13 d2 93 57 fb |#8y...W.| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 39 60 84 ac d0 |..........59`...| -00000010 b9 47 4b 47 49 af 52 88 3c 12 50 0d 65 46 f7 a1 |.GKGI.R.<.P.eF..| -00000020 50 39 c5 39 22 b3 45 e6 d3 25 44 a6 bc 3d bc 69 |P9.9".E..%D..=.i| -00000030 35 1d 61 cf a0 3c 53 77 94 67 66 ae 37 7f 3f 84 |5.a..>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,85 +7,86 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 3d 50 78 7e 02 |....z...v..=Px~.| -00000010 dc 79 3a 32 6b 6a 50 24 90 65 72 5e cd fc 96 18 |.y:2kjP$.er^....| -00000020 e1 47 21 43 50 5a 32 0f cf e7 ae 20 00 00 00 00 |.G!CPZ2.... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 f9 23 d9 5d 6c |....z...v...#.]l| +00000010 ae 6b 63 2a d8 2c a0 27 8e 7b 39 29 35 04 0e a9 |.kc*.,.'.{9)5...| +00000020 31 f7 a0 c5 77 a7 f3 c5 25 ca 2f 20 00 00 00 00 |1...w...%./ ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 cd |..+.....3.$... .| -00000060 e6 a0 65 6b 1c 9e 5c f0 b7 f9 82 8e 37 d1 c4 35 |..ek..\.....7..5| -00000070 31 c1 3f df 4a 70 33 ba 38 d9 3f 74 0c c2 61 14 |1.?.Jp3.8.?t..a.| -00000080 03 03 00 01 01 17 03 03 00 17 63 c3 02 95 17 f4 |..........c.....| -00000090 a8 76 8d 54 ad 3c 10 c7 cc e8 08 13 d6 9b 0b 0f |.v.T.<..........| -000000a0 db 17 03 03 02 6d 0f ec 8d 0d e5 1a 85 02 3f 92 |.....m........?.| -000000b0 44 09 ac e6 da 2d c8 d7 14 68 00 9d 22 bf 05 1d |D....-...h.."...| -000000c0 cd 07 b5 8b b9 84 3f cf cc c5 48 40 00 2e e1 c9 |......?...H@....| -000000d0 0b 41 6d 39 cb 05 00 d6 7a 10 4a ba 96 e1 96 a9 |.Am9....z.J.....| -000000e0 70 d8 20 76 2f d2 70 83 cb a0 d1 72 43 db 09 cd |p. v/.p....rC...| -000000f0 2d e5 89 11 e8 81 15 13 dd 29 2a c8 88 4a d8 73 |-........)*..J.s| -00000100 35 3d 8e 8a 03 ca ed 32 a9 16 bb 71 88 d5 5f a1 |5=.....2...q.._.| -00000110 1b ec ee 9e 3d 8c f4 d0 c2 5b 72 84 3c 75 aa de |....=....[r......).@..| -00000130 3c f4 32 90 c0 25 b7 f0 fc 6b 16 c1 ab 80 69 79 |<.2..%...k....iy| -00000140 5e dd 95 5a ba e4 5a 68 64 a6 44 f5 a2 3a d6 30 |^..Z..Zhd.D..:.0| -00000150 7e b1 27 b1 79 44 ef 79 95 51 75 02 24 2c ea ab |~.'.yD.y.Qu.$,..| -00000160 d5 e1 fd aa 81 55 89 cf bc 9c 11 2b 0b 4a 99 9f |.....U.....+.J..| -00000170 50 93 68 a1 c8 79 3d d8 aa d8 54 e3 d5 1a 97 90 |P.h..y=...T.....| -00000180 33 87 a9 70 1d 9d ba 78 d0 87 8a 98 6f 1b 1e b0 |3..p...x....o...| -00000190 e8 92 78 df 21 61 88 36 fa 14 4b c9 b1 a4 93 88 |..x.!a.6..K.....| -000001a0 b4 26 9a 13 1b 8f 6c 84 bc b1 78 a8 a1 e7 64 4b |.&....l...x...dK| -000001b0 d4 56 37 b6 d1 80 6d 8d 0f c2 2f 0c 0b 9e 42 8e |.V7...m.../...B.| -000001c0 37 e0 9b 73 e4 ab cf 24 43 86 bc d0 40 fd db 4a |7..s...$C...@..J| -000001d0 c1 f6 55 56 e9 54 5c c7 3c 17 36 44 7b 99 7e 03 |..UV.T\.<.6D{.~.| -000001e0 48 f7 a9 cc 4d b9 b4 bf 09 dd 96 37 8c b5 d5 f0 |H...M......7....| -000001f0 bd af 19 0e 82 6c 5d b6 96 ca 98 a2 56 d3 68 f2 |.....l].....V.h.| -00000200 94 cd 7a 94 8d b3 97 16 03 3d 6a 94 5d 66 32 5d |..z......=j.]f2]| -00000210 11 28 d9 7b c1 8e b1 c4 ec b7 54 94 3b 80 f9 b3 |.(.{......T.;...| -00000220 9d 2d 74 3c 02 55 a0 4a 02 b7 61 19 b0 a2 e6 44 |.-t<.U.J..a....D| -00000230 3e c8 81 e3 a4 18 d7 4c 16 d2 fb e3 90 2c 61 71 |>......L.....,aq| -00000240 a0 82 28 48 de 7c 7c bd ba 27 85 e1 fd c9 df ac |..(H.||..'......| -00000250 b2 61 0f 80 f3 86 31 8f c1 a3 dc b6 43 98 c9 0e |.a....1.....C...| -00000260 73 dd 1d cf 61 f6 25 23 44 ca 5a 4c 12 6c bb 35 |s...a.%#D.ZL.l.5| -00000270 32 c4 32 0d cc 8c 11 b9 4a ee 88 92 d6 27 d4 a8 |2.2.....J....'..| -00000280 25 59 1e fe ba 41 63 50 1e b1 e2 c5 75 95 7d 56 |%Y...AcP....u.}V| -00000290 60 ed 81 d0 e7 12 05 e7 0f b4 5d 6f 27 98 76 72 |`.........]o'.vr| -000002a0 e7 8a e1 ff 5d 6b 29 9f 75 24 a5 fd 6d 1f bc 58 |....]k).u$..m..X| -000002b0 f8 b8 67 d1 b0 21 25 f1 09 c7 f9 41 f5 85 1b eb |..g..!%....A....| -000002c0 56 f6 14 83 bb 08 d5 3e ed 22 e1 c5 9c 14 cc de |V......>."......| -000002d0 d3 45 e1 0e e3 cb 61 b5 ab f6 03 41 bc 71 5d 17 |.E....a....A.q].| -000002e0 99 c6 8f 13 41 f8 78 e8 da 3d 40 1c 1a 47 a9 b2 |....A.x..=@..G..| -000002f0 e7 22 90 2f d8 8f 6f 0d 36 02 b1 36 fa 6d 26 6f |."./..o.6..6.m&o| -00000300 82 e2 54 74 a0 26 3c 0c 57 bb d7 01 ff ee 6f 16 |..Tt.&<.W.....o.| -00000310 63 92 00 17 03 03 00 99 ea 68 e4 08 10 2d 6f b6 |c........h...-o.| -00000320 a2 f8 f5 03 35 00 63 c8 da 23 4c 96 b8 2a 5c f5 |....5.c..#L..*\.| -00000330 9d 24 6f 5a 5b c3 aa d2 df d9 16 b6 9a 91 79 39 |.$oZ[.........y9| -00000340 18 35 65 28 80 97 fe 76 26 79 45 80 4c 8a 7c cc |.5e(...v&yE.L.|.| -00000350 a2 36 1a 8a ad aa f3 06 08 1f b7 4a 9b 22 7f 37 |.6.........J.".7| -00000360 62 3a ae 13 c0 f4 22 05 6f fc 92 5a e0 ed f1 5b |b:....".o..Z...[| -00000370 c6 6b 4f 18 83 a6 39 a7 5c 1c 53 32 08 76 25 03 |.kO...9.\.S2.v%.| -00000380 20 d5 47 57 76 06 38 4e bd b8 dd 7f 0e 37 b3 4e | .GWv.8N.....7.N| -00000390 f1 f3 b1 98 d4 f0 d6 00 ea 6a e9 ec a4 b0 fd 20 |.........j..... | -000003a0 2d 67 20 c8 ef 9f a1 97 00 cd 15 c2 8e c2 ba 46 |-g ............F| -000003b0 76 17 03 03 00 35 d0 f3 18 d0 71 4c 66 8c 40 ef |v....5....qLf.@.| -000003c0 57 92 f3 56 5a 42 1e 4c e6 13 5a cc ab 26 90 6a |W..VZB.L..Z..&.j| -000003d0 9b ca 49 b0 81 ec 38 30 44 27 5a fa ac d6 1f 5c |..I...80D'Z....\| -000003e0 bc 64 4b 0b c3 69 b2 5b ef 7f 4a |.dK..i.[..J| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 ba |..+.....3.$... .| +00000060 2b 6b 27 27 14 c0 42 b6 1f bc ad 77 f1 1f 4a b3 |+k''..B....w..J.| +00000070 42 94 a6 3a 2c 7f e6 aa 72 8e d0 70 e8 0e 53 14 |B..:,...r..p..S.| +00000080 03 03 00 01 01 17 03 03 00 17 33 bb 8a 47 b0 a9 |..........3..G..| +00000090 29 d7 bf e4 94 7d 42 8a 19 95 4e d9 7c b7 9a 87 |)....}B...N.|...| +000000a0 83 17 03 03 02 6d 86 a7 6c 3c 4e 45 95 f6 f6 66 |.....m..l.`.`~.....r| +000001d0 a4 bc 66 a7 bd 46 83 88 6e 9f b3 db de e7 b3 04 |..f..F..n.......| +000001e0 62 4c 61 d6 d0 89 84 e4 30 d7 4d a0 61 4f 56 ad |bLa.....0.M.aOV.| +000001f0 51 c6 1f 10 01 9e 8d 75 55 fb 89 b8 d0 57 e3 ce |Q......uU....W..| +00000200 40 72 41 27 96 e0 5b f4 cc ba d0 ec 8c d4 91 ca |@rA'..[.........| +00000210 8f f0 db 11 86 d5 8e 02 6a 1f 29 00 f6 ff 42 a2 |........j.)...B.| +00000220 7c c9 e7 18 38 39 c9 e4 2b 0e e9 36 40 d3 dd bc ||...89..+..6@...| +00000230 f7 e3 7c 2d e9 f0 52 31 16 85 b4 e2 a8 54 cd d0 |..|-..R1.....T..| +00000240 d6 e2 ed f4 fc 91 9f 50 68 a0 74 af 37 c7 4c bd |.......Ph.t.7.L.| +00000250 de 9e c7 78 06 41 6b 62 07 8c 8b f4 f5 ea ab 16 |...x.Akb........| +00000260 b0 16 b9 ea 06 2c ee 66 d5 da b3 2c 0f 03 d2 f6 |.....,.f...,....| +00000270 ae f7 11 85 d8 b6 b8 bf 7e a5 c8 ff 0d 41 29 86 |........~....A).| +00000280 94 e4 32 58 6c 0e 05 47 b8 c5 77 de d1 81 8d 72 |..2Xl..G..w....r| +00000290 d4 e0 64 66 f7 17 8a 96 88 bf 1c 04 22 40 e0 cf |..df........"@..| +000002a0 28 6d f5 4f 89 e2 4a 23 4b 71 e1 15 3b da 45 0b |(m.O..J#Kq..;.E.| +000002b0 13 ee 1f 7f 4e 45 3d 8e d2 f3 bd 23 e7 4c f3 d2 |....NE=....#.L..| +000002c0 0f 4b 6e 6a 3d 6a f1 26 b7 ae f6 1d 39 73 cd fd |.Knj=j.&....9s..| +000002d0 1c c8 c7 45 fa e0 67 d5 2c eb e9 2b 32 8e 65 7b |...E..g.,..+2.e{| +000002e0 c5 32 cc e6 01 91 fc fd 92 6e ab 9a 13 f6 63 81 |.2.......n....c.| +000002f0 e5 b9 25 6d ce 73 39 9e 82 ae 18 89 a5 32 cb d3 |..%m.s9......2..| +00000300 a3 85 55 f5 cd 26 96 18 91 1c 41 36 69 49 93 f2 |..U..&....A6iI..| +00000310 aa 05 ab 17 03 03 00 99 9c 1d 79 c5 7b 73 b9 f9 |..........y.{s..| +00000320 00 2d ea ff c2 8d f6 57 65 7c 92 fa ba 22 18 03 |.-.....We|..."..| +00000330 69 69 e9 05 e0 74 1a e5 9d f9 30 9f 1c 39 86 30 |ii...t....0..9.0| +00000340 aa 1b 86 fa 20 26 20 13 ea 8d eb 8b 4e 8b c1 50 |.... & .....N..P| +00000350 86 ef a3 c5 8e 48 b2 a1 5a ac 05 e7 8f 23 8a 34 |.....H..Z....#.4| +00000360 ab 1f 8e 90 b1 e5 9a d3 d7 28 90 b6 12 35 dc cb |.........(...5..| +00000370 c5 3c 8d 3d fc e2 99 2a 8b f0 6a f4 8b a9 62 3f |.<.=...*..j...b?| +00000380 b6 19 29 fd 79 b9 35 72 b0 89 59 ab 78 c6 c9 f0 |..).y.5r..Y.x...| +00000390 68 bc 0d f5 9a 45 dd 4f d2 40 75 19 47 af e9 6f |h....E.O.@u.G..o| +000003a0 56 ec 73 ce cd 19 31 c0 39 08 b1 63 e0 ac d4 49 |V.s...1.9..c...I| +000003b0 e5 17 03 03 00 35 0d 34 de e9 22 e4 56 18 4a 33 |.....5.4..".V.J3| +000003c0 d1 05 c4 d4 f2 64 24 62 d7 da 6a 8e 34 3b 51 13 |.....d$b..j.4;Q.| +000003d0 27 69 88 37 4b ba 29 9d c5 78 af 62 2b 62 6e 5a |'i.7K.)..x.b+bnZ| +000003e0 28 7a 93 c5 9a f3 84 1d 50 9a 94 |(z......P..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 ef 3b a2 4d 0f |..........5.;.M.| -00000010 69 53 f2 a3 80 a0 06 a9 99 a9 15 1e bc 8b 4a 08 |iS............J.| -00000020 de 87 e7 b6 10 d6 b3 fc 89 f8 24 f9 2d 04 a1 fd |..........$.-...| -00000030 c2 ce eb 14 e9 df bf ab 80 8e f1 00 53 60 88 82 |............S`..| -00000040 17 03 03 00 17 22 aa a9 e0 1f f8 55 03 22 9b 0f |.....".....U."..| -00000050 b2 6d 73 be 10 5d 6c c6 d8 0e 5e 0d 17 03 03 00 |.ms..]l...^.....| -00000060 13 45 f2 81 7f ea ae 0d 77 bb d4 05 1e 55 af a8 |.E......w....U..| -00000070 3e 0d 10 0f |>...| +00000000 14 03 03 00 01 01 17 03 03 00 35 4f 9c 2d 01 8b |..........5O.-..| +00000010 4a 31 16 77 b4 f2 2b 40 cb 8e d5 7d 93 bd 66 59 |J1.w..+@...}..fY| +00000020 f8 f1 f4 45 69 fd f7 9b 88 5a e5 0a 40 67 e2 17 |...Ei....Z..@g..| +00000030 72 de b0 1d 02 ba b5 a7 58 35 4a 3e b6 2a 0c e8 |r.......X5J>.*..| +00000040 17 03 03 00 17 4a 50 b7 f1 94 a4 64 9e a2 95 0a |.....JP....d....| +00000050 6c f6 93 7f d6 6d 12 10 7a 69 8a d2 17 03 03 00 |l....m..zi......| +00000060 13 10 60 24 3f 6e c9 ee c6 27 50 72 5e 19 22 e0 |..`$?n...'Pr^.".| +00000070 76 12 45 e5 |v.E.| diff --git a/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA b/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA index 8984790aab6..6611cdfed22 100644 --- a/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA +++ b/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,134 +7,135 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 ea 8b 99 cb 5b |....z...v......[| -00000010 d8 fb e9 14 7f 17 20 9c b8 41 01 dd ce 8a 90 4e |...... ..A.....N| -00000020 a9 f0 fb eb 71 37 24 02 d2 ee 96 20 00 00 00 00 |....q7$.... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 ea 4e 78 a5 f4 |....z...v...Nx..| +00000010 71 78 37 5b 2c e4 69 b2 00 4d 49 8c 8b 86 4c 80 |qx7[,.i..MI...L.| +00000020 f9 db 03 3f cc 1e 42 f9 87 ff 7b 20 00 00 00 00 |...?..B...{ ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 c8 |..+.....3.$... .| -00000060 c6 52 8e 3c 6f 0d ab 2d be 4c e0 01 c8 af 1f 8e |.R........t| -00000100 69 88 5d 8e a4 fa 02 b0 6f f4 0e 38 cc 95 12 e2 |i.].....o..8....| -00000110 f1 e3 47 89 a6 1d 80 26 cb 23 6e f3 83 1c e4 85 |..G....&.#n.....| -00000120 7b 1a 4d 12 c8 bf ff 07 39 a9 4e 4e d7 45 35 23 |{.M.....9.NN.E5#| -00000130 9b f9 59 6d a5 b0 49 1b 5f e7 42 62 17 00 1e 57 |..Ym..I._.Bb...W| -00000140 53 c5 22 fb 05 89 fd fe 5d de 71 e8 26 fd 6d e3 |S.".....].q.&.m.| -00000150 fc b9 cb 1f d5 d4 84 d1 67 fe 8a a0 74 ff ad ff |........g...t...| -00000160 c8 35 fe c2 9a 17 33 18 51 c2 cd 19 7c dc 5d c5 |.5....3.Q...|.].| -00000170 7c e6 d0 38 ab 28 0b 8c 78 51 aa 7f ef f0 9a c3 ||..8.(..xQ......| -00000180 df 26 d2 bc 1b b6 98 b1 16 35 9d f0 73 b7 15 f7 |.&.......5..s...| -00000190 7d 9f 3e fe 4c 75 e7 c7 5d cb c2 e5 29 4a 30 32 |}.>.Lu..]...)J02| -000001a0 e2 da 3c 2c 16 ba 89 41 28 5c 33 75 b3 ed d1 e6 |..<,...A(\3u....| -000001b0 4f f6 bb 33 62 53 9d be fe d3 53 b5 bd 3e e3 b5 |O..3bS....S..>..| -000001c0 0a 37 67 60 33 c3 72 a8 ea 55 73 3c b2 7f ed 8b |.7g`3.r..Us<....| -000001d0 59 5e 44 e4 76 0d 1e 3c 3e 1c 9c 8c 86 3d 0a a3 |Y^D.v..<>....=..| -000001e0 78 bd 13 77 eb dc 22 e5 96 ff ae 44 94 cd ef ae |x..w.."....D....| -000001f0 ca 64 ec 06 a1 38 49 17 ce a5 c4 34 86 fd 55 1f |.d...8I....4..U.| -00000200 32 31 d5 b0 8c d6 b5 bc b8 29 29 97 b5 39 a0 f8 |21.......))..9..| -00000210 b1 b5 72 24 ff ce 6f 7d 6a 0d 18 26 8f 9a e8 d3 |..r$..o}j..&....| -00000220 e6 e0 7c 9c 56 45 ca 48 44 69 05 53 40 eb 96 c5 |..|.VE.HDi.S@...| -00000230 17 aa 28 56 20 ee 82 fd de d1 55 b8 e9 27 ae 3d |..(V .....U..'.=| -00000240 e1 44 d6 0b b9 7a 25 77 b0 f1 be 64 ae cc 0d 44 |.D...z%w...d...D| -00000250 af 57 32 9f cf bc c0 07 00 0b 19 97 08 0a d5 50 |.W2............P| -00000260 20 0e ef d5 1e 2e 68 82 ae 2d 84 47 3d 9b 5b 24 | .....h..-.G=.[$| -00000270 55 95 b2 93 e0 60 a2 cd e5 72 69 b3 e2 de da 70 |U....`...ri....p| -00000280 76 88 be 1f 5a 8e 7a d8 ff 94 db b0 92 b2 a1 a1 |v...Z.z.........| -00000290 26 5b 3b d5 5e 67 16 b7 6a 9f dc ab 21 7e df 6e |&[;.^g..j...!~.n| -000002a0 2a 73 e9 20 40 4b c8 34 fc 4b be f6 d8 ba 78 d7 |*s. @K.4.K....x.| -000002b0 a4 c2 ed a9 52 f9 ea 88 67 5e 10 92 8f ba 83 cd |....R...g^......| -000002c0 19 79 82 c5 76 06 d9 98 9f 68 2e 34 82 2f 9a 41 |.y..v....h.4./.A| -000002d0 fb 63 b6 8c 79 56 62 9d bb bc b5 22 ab 28 35 f7 |.c..yVb....".(5.| -000002e0 bc c6 a8 6b e7 86 01 c3 6c e5 88 28 57 09 65 31 |...k....l..(W.e1| -000002f0 b2 5c 0a 60 46 af 94 2c d4 37 49 9b 4c e4 4b bb |.\.`F..,.7I.L.K.| -00000300 fb 0d 87 94 82 11 09 26 04 6f ec e9 a6 f4 9c ca |.......&.o......| -00000310 79 a0 d0 48 32 5a 02 58 70 81 d0 b6 6d 77 2f 6f |y..H2Z.Xp...mw/o| -00000320 4e 9b db ca 82 38 ed a6 60 8e e2 b6 14 33 f5 02 |N....8..`....3..| -00000330 4b 97 a4 86 2f 43 9d ee 88 2c 1c 58 7e 47 30 cc |K.../C...,.X~G0.| -00000340 ec 0d aa 22 13 60 be e2 c9 c4 59 90 67 96 9b 2a |...".`....Y.g..*| -00000350 41 79 49 00 71 80 e9 0d 12 c3 17 03 03 00 99 ec |AyI.q...........| -00000360 f5 a1 45 64 61 fc 61 35 d5 2f bf 20 02 68 0b 10 |..Eda.a5./. .h..| -00000370 df c4 4b e7 2c 43 bc f5 3d 0b 7e 9f a4 71 09 2c |..K.,C..=.~..q.,| -00000380 a6 cf f4 f4 b4 2c 08 0c 03 50 ac 47 74 ad 24 f1 |.....,...P.Gt.$.| -00000390 04 f3 d4 83 42 3f 35 a5 57 ff ab 59 0c 9a a2 ca |....B?5.W..Y....| -000003a0 6c 30 b7 87 73 af 53 f9 1d 6b e7 44 ec d1 bd 14 |l0..s.S..k.D....| -000003b0 15 09 cf ff 82 5e a2 6d ba 00 53 b8 b3 7c 0e e5 |.....^.m..S..|..| -000003c0 d1 e2 a2 38 25 88 aa ee 93 c8 d9 d1 88 42 42 90 |...8%........BB.| -000003d0 43 8d 22 d8 48 02 57 22 6a f4 e9 23 71 f0 64 30 |C.".H.W"j..#q.d0| -000003e0 6a 68 12 a5 3c 8c 61 5e bc 73 91 6a 01 3a 14 14 |jh..<.a^.s.j.:..| -000003f0 86 7c 4d f5 aa cc 2f f5 17 03 03 00 35 7e f6 f5 |.|M.../.....5~..| -00000400 6b 75 e2 63 64 5a 6b 9b ce 6b 76 d7 47 bc 1b 47 |ku.cdZk..kv.G..G| -00000410 9e 68 25 fe 47 2b 06 a9 72 d0 a7 3f 23 3d 71 4a |.h%.G+..r..?#=qJ| -00000420 da 29 fb e3 dd ee e6 f6 a5 32 cc eb da 61 2b 52 |.).......2...a+R| -00000430 24 26 |$&| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 f1 |..+.....3.$... .| +00000060 bf 65 1e fd e0 5d 1b ca 02 b5 9e 3f a8 82 e0 5a |.e...].....?...Z| +00000070 97 eb af b5 f1 f7 77 3f 46 a8 66 93 de a8 39 14 |......w?F.f...9.| +00000080 03 03 00 01 01 17 03 03 00 17 16 a7 f6 48 b9 11 |.............H..| +00000090 59 75 3d d8 cf eb ba 72 6c f7 0d 26 50 ab 2d 2a |Yu=....rl..&P.-*| +000000a0 61 17 03 03 00 42 00 0f 78 f4 5a 62 c5 56 bd f5 |a....B..x.Zb.V..| +000000b0 4a df d3 78 76 bd 90 71 49 69 8a b3 60 5b 24 8b |J..xv..qIi..`[$.| +000000c0 45 fb c7 e0 ff 04 d8 7b c6 1f 93 c9 f9 b8 0d 38 |E......{.......8| +000000d0 53 d1 2e 95 99 32 52 2e 45 b2 11 08 45 c7 bc 64 |S....2R.E...E..d| +000000e0 6a c2 32 db 70 96 77 6f 17 03 03 02 6d ba 3e 97 |j.2.p.wo....m.>.| +000000f0 ea d7 dd c1 c5 39 9a c4 b1 eb 8b df 35 57 43 35 |.....9......5WC5| +00000100 31 7a 4c 71 ab 57 79 80 f9 48 96 67 5f 3b fe 98 |1zLq.Wy..H.g_;..| +00000110 0b 5d d0 ce 8c 0c 5a 03 28 8f 64 b4 3e 74 75 51 |.]....Z.(.d.>tuQ| +00000120 81 b3 09 a7 8e 33 45 92 49 72 91 b7 2c 45 68 5c |.....3E.Ir..,Eh\| +00000130 ee 27 e8 5b fd b0 80 e3 43 35 2f a2 bd e5 cf d6 |.'.[....C5/.....| +00000140 c3 fc 43 03 1e aa c9 c4 67 db ef 0c c3 aa 46 18 |..C.....g.....F.| +00000150 39 69 31 26 7f 0a 7a b2 e7 c4 cb 09 3a f1 8e a0 |9i1&..z.....:...| +00000160 05 70 87 a9 12 c6 f2 a1 25 87 72 0a 2d fb d5 51 |.p......%.r.-..Q| +00000170 ce 93 8e f8 08 0e 86 90 04 00 9b 76 fd 57 23 cb |...........v.W#.| +00000180 bc 78 23 07 8a 35 92 6e d6 cd f5 b5 2e e1 8f 33 |.x#..5.n.......3| +00000190 7a bb 61 54 65 4f 4d 12 4b ca db 19 4b 30 6e 2c |z.aTeOM.K...K0n,| +000001a0 56 62 b5 32 7a 98 b6 a4 10 98 5a 16 6b 26 8e 7c |Vb.2z.....Z.k&.|| +000001b0 e0 88 77 a6 20 60 c9 fb c5 e2 66 c3 6d 0d df dd |..w. `....f.m...| +000001c0 21 22 10 da 88 24 21 92 74 3b d8 92 c0 ec 2f 57 |!"...$!.t;..../W| +000001d0 79 d7 42 bd d7 b0 e0 23 d2 a0 45 7f 2a 2a ff df |y.B....#..E.**..| +000001e0 a4 61 53 ec 44 e2 3a 7a 06 15 8a ce 02 84 e7 78 |.aS.D.:z.......x| +000001f0 9b ef 15 0e 84 16 fe 0f dd 36 de 0f 69 14 e4 35 |.........6..i..5| +00000200 90 e4 a0 15 a6 97 e5 c9 a1 3c ed 79 c6 03 ae 39 |.........<.y...9| +00000210 f2 36 1e ca 20 4f 20 59 e6 6f c7 15 ba 90 ac 4a |.6.. O Y.o.....J| +00000220 11 ad 3e f5 48 df 94 fe f8 48 2f 12 25 01 6c 9a |..>.H....H/.%.l.| +00000230 e6 ee 41 7b 13 4c 2f cc 3a 2d 8d b8 e7 d5 62 88 |..A{.L/.:-....b.| +00000240 88 5d d4 6e c4 64 c5 32 0a e7 86 08 64 2c 0a 11 |.].n.d.2....d,..| +00000250 8e 51 63 f9 81 30 00 b1 29 fa b8 1c ab 87 88 22 |.Qc..0..)......"| +00000260 f0 ef 79 04 8c 85 78 df 72 6c 99 d6 c7 3a 9f 2a |..y...x.rl...:.*| +00000270 6d c6 24 05 e7 e5 d7 d0 c7 e5 7c 87 50 f9 b7 69 |m.$.......|.P..i| +00000280 6d 1f 39 77 5d 4c f2 98 35 f7 07 b6 30 0d d6 25 |m.9w]L..5...0..%| +00000290 40 cb a4 2d b2 f1 22 ca 26 5d 92 22 97 0a 65 a9 |@..-..".&]."..e.| +000002a0 a0 46 58 be 0d af a1 1c da c8 bf 98 28 72 ea ee |.FX.........(r..| +000002b0 46 f9 c0 0d b3 f1 11 12 5f b7 69 75 ea dd 60 d0 |F......._.iu..`.| +000002c0 53 51 01 ec 7c ff ef 41 68 04 ec a4 6b 51 bb 89 |SQ..|..Ah...kQ..| +000002d0 8b 8d a2 89 05 6f 78 81 16 f8 7a c2 f6 c3 0d ef |.....ox...z.....| +000002e0 b3 12 e2 57 54 95 a6 cd 5d 04 32 88 70 f9 db db |...WT...].2.p...| +000002f0 b3 45 75 32 6f ac 9a fa ad 54 e5 a5 82 ae 3e 73 |.Eu2o....T....>s| +00000300 2d 07 f4 48 83 e2 10 7d cb 2f 4c 18 94 75 37 24 |-..H...}./L..u7$| +00000310 cd 13 dc 3a 56 93 e8 80 a3 ba de b1 0d 14 79 48 |...:V.........yH| +00000320 08 69 a6 f3 2e 9f 7a 78 6e 9c de 16 ba 73 0b a6 |.i....zxn....s..| +00000330 f2 6c 04 e6 e6 89 3d 46 7d db a4 8f 9a e7 5d 0e |.l....=F}.....].| +00000340 b9 6b 05 59 4d 4d e9 48 1a 18 e9 59 7b 56 70 d6 |.k.YMM.H...Y{Vp.| +00000350 0f fc c2 93 31 03 fa ad b4 c9 17 03 03 00 99 62 |....1..........b| +00000360 c5 b8 11 10 72 af 5b 36 7b 4b 86 83 05 1f 5a c5 |....r.[6{K....Z.| +00000370 66 7b b6 ac 30 8d c0 03 64 ec 29 5d 60 e9 e9 9d |f{..0...d.)]`...| +00000380 6d 58 3e 55 7e 19 a3 59 f5 8b ca 1a f0 c8 ca 1b |mX>U~..Y........| +00000390 c6 ed 7f d7 70 fb 4b a5 6a 96 66 ce 4c 96 d1 b4 |....p.K.j.f.L...| +000003a0 de 99 e2 31 4a 88 64 51 7b 73 60 bb 5c 46 9b b7 |...1J.dQ{s`.\F..| +000003b0 9f d8 97 de 03 06 f3 3e 34 8b 75 43 ce cd 9a 12 |.......>4.uC....| +000003c0 1e 27 b5 28 5e 8f b6 04 d2 02 19 02 02 72 85 46 |.'.(^........r.F| +000003d0 1c cb 5e 63 09 e6 ba 81 69 29 97 5f 31 1e 8f f5 |..^c....i)._1...| +000003e0 1a ed 3b 1e 97 83 bf ee 1f 09 f4 f7 be 32 c7 bc |..;..........2..| +000003f0 b6 7e 70 b9 32 4b 07 99 17 03 03 00 35 67 1c 72 |.~p.2K......5g.r| +00000400 de 27 25 26 1b 12 b2 9a a3 38 5c a7 f7 13 a4 1e |.'%&.....8\.....| +00000410 bf f9 7f 1d 57 af ff 2f 89 4b 75 fc 23 c5 47 00 |....W../.Ku.#.G.| +00000420 cd b7 b6 89 af 4e f0 17 e9 e6 31 cd fb b0 31 19 |.....N....1...1.| +00000430 73 61 |sa| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 1e 67 f8 08 c4 15 |...........g....| -00000010 47 a9 da 91 df f1 61 0f 50 21 f6 da dd a9 a6 e4 |G.....a.P!......| -00000020 00 05 29 62 d2 cc fe 14 57 a2 aa 46 16 b3 46 6e |..)b....W..F..Fn| -00000030 82 87 dc bb 1a d9 e7 c6 e9 1a 3b 7e a5 94 9b 7e |..........;~...~| -00000040 bb 07 b8 f3 de cc f1 85 d5 ee ff 0b 5a 19 c1 e3 |............Z...| -00000050 5f 47 f4 81 f4 d3 2d 85 f8 38 90 00 10 54 9a 3e |_G....-..8...T.>| -00000060 56 e4 99 a5 31 b1 dc d4 77 fe 28 3a b4 3e 63 42 |V...1...w.(:.>cB| -00000070 bc 05 c7 8a e5 d9 01 5c c9 18 39 1e 62 4f b4 58 |.......\..9.bO.X| -00000080 d3 9a 6a e1 a4 d3 ef 7f b8 0f 35 ac 2a 4a ba 77 |..j.......5.*J.w| -00000090 24 1e 24 6e 0e a2 8e f1 ba 5f fe 24 03 ed 1d e7 |$.$n....._.$....| -000000a0 43 2d fb bb 2e a9 a5 9a 18 11 39 99 a1 5a b7 92 |C-........9..Z..| -000000b0 37 91 f2 80 b2 f6 57 87 f9 a5 d9 da 36 b5 db 1a |7.....W.....6...| -000000c0 28 d8 9e f7 92 6f cf 0c 57 9a 95 42 ef 6a 50 f6 |(....o..W..B.jP.| -000000d0 38 4f 74 52 09 34 ca 8a d8 c7 a2 d2 69 bb db 13 |8OtR.4......i...| -000000e0 b1 ef f2 6d d3 f0 dd 5d b7 93 25 87 84 cd 87 6d |...m...]..%....m| -000000f0 c7 24 99 2b c8 02 25 1c 58 bc 98 03 33 15 ee 3e |.$.+..%.X...3..>| -00000100 96 d0 af 82 c7 74 71 ec ef a6 eb 88 20 55 1b fa |.....tq..... U..| -00000110 ea 01 38 5b 68 77 f1 3b 2a e6 d1 96 bc 28 b3 97 |..8[hw.;*....(..| -00000120 47 94 14 3f 6b 73 82 bf b0 ba fe 45 2a 45 45 1c |G..?ks.....E*EE.| -00000130 30 68 f5 74 07 15 18 00 a7 4f 62 df 7c ff 4c 0a |0h.t.....Ob.|.L.| -00000140 93 d6 60 8b 1f 0e 7f d3 88 43 90 f6 18 05 f1 ae |..`......C......| -00000150 ac 04 63 8b 43 b8 11 74 b1 87 e6 bc 2d 72 4a 2e |..c.C..t....-rJ.| -00000160 75 ab 16 5e 0e bc 76 6d d6 0e bc 39 0d 3c 76 01 |u..^..vm...9.fDcKC.%(D.-.| -000001b0 39 0e cd 15 a3 04 d9 db 4f a4 03 cb d2 84 da 41 |9.......O......A| -000001c0 5c 60 bf 00 77 19 68 b1 50 99 c2 88 d2 56 1e 29 |\`..w.h.P....V.)| -000001d0 c9 8c 83 98 7a 2f 04 e6 d6 09 5c 27 af a7 69 c4 |....z/....\'..i.| -000001e0 f7 4a ed b5 db d3 7a aa 75 f1 b2 8d 87 15 9a d1 |.J....z.u.......| -000001f0 00 fa 7f 58 06 2d 72 2b f7 27 b3 5b 76 57 21 35 |...X.-r+.'.[vW!5| -00000200 80 ce 8e bd e4 bb 45 01 c4 6b 43 f1 44 0a 5f 21 |......E..kC.D._!| -00000210 76 48 ae ce 8e 1d ba f7 7c 4f ae a2 d8 77 ce 9c |vH......|O...w..| -00000220 6d 69 b7 1e 78 ab 02 ed 15 17 03 03 00 a3 84 ed |mi..x...........| -00000230 ba 37 b6 6f 96 68 ef 9e b7 c6 23 5a 9f 1b ed ad |.7.o.h....#Z....| -00000240 3b 5d ab d4 22 d8 3e ab db db c5 b9 57 f8 68 d1 |;]..".>.....W.h.| -00000250 93 d5 36 fe 0c c0 fe 29 88 8b 63 ac 0e 06 4e bd |..6....)..c...N.| -00000260 9e b9 24 65 b5 9c e7 b9 58 4c 8a 07 10 9c 17 f7 |..$e....XL......| -00000270 c0 67 af ff c8 ff fc 87 1b fa c8 21 21 17 2d 43 |.g.........!!.-C| -00000280 f5 fc 4f 0d bf 01 58 b6 f1 58 08 39 f4 0d 94 69 |..O...X..X.9...i| -00000290 8f f0 c1 14 93 41 56 32 41 11 84 58 73 13 69 2a |.....AV2A..Xs.i*| -000002a0 ed 2a 34 61 73 8d 47 41 62 33 39 66 fa 3d 2a e5 |.*4as.GAb39f.=*.| -000002b0 bf 09 d6 c0 1e 3c 98 b3 86 a6 87 b5 a7 d2 cf d9 |.....<..........| -000002c0 dd f8 2e 86 f7 13 84 4a f7 3b ec 8e e5 06 f5 cd |.......J.;......| -000002d0 42 17 03 03 00 35 b2 38 87 30 58 9e 03 6e 44 dd |B....5.8.0X..nD.| -000002e0 fb 87 11 3a a0 e7 c1 2d 74 3b 35 d0 3f bc de cd |...:...-t;5.?...| -000002f0 71 61 8b 7c a5 7e c6 2d 76 67 44 9e 75 e5 9b 3b |qa.|.~.-vgD.u..;| -00000300 c5 2b 42 8a 4a 7f 0e 12 4c 2e 0f 17 03 03 00 17 |.+B.J...L.......| -00000310 d3 61 ed 75 dd 2e ee dd 79 fe d1 7c 4d 23 b1 95 |.a.u....y..|M#..| -00000320 ea 14 d6 27 d0 02 46 17 03 03 00 13 84 c1 07 6f |...'..F........o| -00000330 1c c6 22 a8 ae 6d a8 e8 62 54 ac b2 53 57 bb |.."..m..bT..SW.| +00000000 14 03 03 00 01 01 17 03 03 02 1e e9 c3 0a e9 35 |...............5| +00000010 c0 d7 d8 1e 01 13 31 2c 39 0c 31 57 df f2 8d 7f |......1,9.1W....| +00000020 ca 2e 8c a0 63 60 e2 61 c6 37 8f cf 66 62 e7 d6 |....c`.a.7..fb..| +00000030 3d 89 6b 3b bd 1c 45 ec 62 a5 1c b3 86 16 bc 03 |=.k;..E.b.......| +00000040 57 9e 2b cd 31 d4 4d ad 57 96 12 12 19 ce 61 14 |W.+.1.M.W.....a.| +00000050 d6 1f 7a d1 c8 9b d4 9e 18 cf 1c f7 d0 ca 84 bb |..z.............| +00000060 8e 93 85 97 4b 53 68 3d f6 45 76 e0 a7 42 df 6a |....KSh=.Ev..B.j| +00000070 96 04 b9 9e 03 97 bb 57 bf 7f 9c 27 68 ba 04 49 |.......W...'h..I| +00000080 a7 c9 a3 f3 77 83 1f 15 0e 02 05 b5 8c e4 a6 ed |....w...........| +00000090 f8 65 5b bb a4 65 08 a1 a3 34 2a 71 66 6c 2e c8 |.e[..e...4*qfl..| +000000a0 e2 5b 08 ca 59 91 da 07 14 61 17 b7 19 28 00 33 |.[..Y....a...(.3| +000000b0 d9 0c 45 df d8 74 83 2e 9b 99 c7 35 cd f4 de 53 |..E..t.....5...S| +000000c0 b0 df 5c 8b 15 b0 e0 81 77 a5 5d d5 33 40 51 60 |..\.....w.].3@Q`| +000000d0 09 36 4f b6 6f ce 95 2b d1 38 88 33 e0 13 a0 c1 |.6O.o..+.8.3....| +000000e0 5f 2c 15 77 56 d1 16 09 9a 78 5c 6f 8c 93 c3 44 |_,.wV....x\o...D| +000000f0 54 04 b4 d3 23 31 ff 61 74 e5 09 3a d3 9b f1 2f |T...#1.at..:.../| +00000100 de f4 a9 0b b8 9d ca 17 2c 3f d5 2b dd c0 9e 07 |........,?.+....| +00000110 48 50 6a 51 72 be 92 10 1a 91 b5 2d 39 76 10 a4 |HPjQr......-9v..| +00000120 42 63 31 df ce 31 9a 5c 0d ee 6e 55 c0 ba 44 9f |Bc1..1.\..nU..D.| +00000130 e4 75 77 0f 88 6d 1d 24 9f 1c a0 12 14 4c ce 68 |.uw..m.$.....L.h| +00000140 24 a5 aa f2 f2 c5 f4 4f a9 c7 e0 dd 5c 6b 4c 53 |$......O....\kLS| +00000150 b5 26 8b e2 a4 af e3 13 77 0a fc dd 2b 56 fa a2 |.&......w...+V..| +00000160 46 7f 9a 11 c6 a0 4c b6 36 29 93 9f 83 99 13 ad |F.....L.6)......| +00000170 a0 62 9a ef 42 d0 dd 49 fe ba e4 fd fd 09 4b d4 |.b..B..I......K.| +00000180 31 6e d9 a5 0e 4d ac 8c 90 7c 26 2b 6b 1a cb 55 |1n...M...|&+k..U| +00000190 47 53 47 e2 d4 a1 d8 2e 5d 9b 36 75 f0 a4 8a 39 |GSG.....].6u...9| +000001a0 88 07 c8 ed 75 40 fd 72 0e 57 02 a6 bf 8a 64 0a |....u@.r.W....d.| +000001b0 98 8a 1c f4 d3 3d c4 af 7d 97 6e b7 e0 f6 d8 10 |.....=..}.n.....| +000001c0 17 0b d1 5c f9 41 c9 5e 5c 8a 38 dd 66 b3 e9 74 |...\.A.^\.8.f..t| +000001d0 41 2a bd 2d f8 6a 27 57 da ef d6 ca 70 49 c6 e2 |A*.-.j'W....pI..| +000001e0 94 ef 1e c6 57 a0 c8 fc d1 05 4f 65 c1 71 e4 ab |....W.....Oe.q..| +000001f0 44 49 f3 e3 6d b1 f4 5a 69 e7 70 30 b5 81 19 3a |DI..m..Zi.p0...:| +00000200 06 33 ef a5 bd 81 8c 3c 7b 2f 9f 41 a5 7d a8 5f |.3.....<{/.A.}._| +00000210 3b 3d 95 6e 04 a8 5f 2a c1 de 6e e4 14 17 91 36 |;=.n.._*..n....6| +00000220 9d 57 9c 34 1a 7d c8 c3 42 17 03 03 00 a3 a0 20 |.W.4.}..B...... | +00000230 06 7e 90 c8 0a b2 db 90 28 38 8f 42 12 89 1d 21 |.~......(8.B...!| +00000240 04 b3 a6 7b 8c 63 60 49 33 4a 70 4b 1a 97 90 51 |...{.c`I3JpK...Q| +00000250 d2 13 6e 56 9a 1d 41 9c 65 19 31 43 56 96 e2 50 |..nV..A.e.1CV..P| +00000260 77 17 67 6e df 3b e1 43 22 fe 0c 49 74 ff b0 e9 |w.gn.;.C"..It...| +00000270 5c f2 66 4e a3 e5 ac 02 1c 69 11 ce de a1 d4 6b |\.fN.....i.....k| +00000280 1c 46 97 02 7e 81 d8 29 78 42 82 5e b7 e2 31 02 |.F..~..)xB.^..1.| +00000290 fb 74 e2 a6 5e 29 f1 28 cf 8a 9c bd f8 a0 09 45 |.t..^).(.......E| +000002a0 67 7e d7 7d 91 8d fe 43 03 92 16 b1 67 cc 7a 32 |g~.}...C....g.z2| +000002b0 7e 3a 88 fc 77 36 b5 69 07 09 a0 1c 5c 76 a7 68 |~:..w6.i....\v.h| +000002c0 93 1a 35 20 f6 c1 20 c7 8f de c9 da 81 25 7a 08 |..5 .. ......%z.| +000002d0 e0 17 03 03 00 35 fa 5b 68 55 45 ee dd d6 a2 cb |.....5.[hUE.....| +000002e0 09 a7 21 23 43 9c c4 ff 1c d6 66 4c ce e1 bd a9 |..!#C.....fL....| +000002f0 77 22 0b b0 d4 ad f9 23 a7 1c 0e 63 27 36 16 c6 |w".....#...c'6..| +00000300 a2 f8 00 ef 36 22 89 a7 d6 76 da 17 03 03 00 17 |....6"...v......| +00000310 ca d3 97 3a 7d cc a0 95 02 4a a8 d8 dd 6d 26 64 |...:}....J...m&d| +00000320 92 be 64 86 00 d9 bf 17 03 03 00 13 18 1e 4f 7b |..d...........O{| +00000330 f9 1a 63 8a 50 6a ee 81 07 76 53 a9 95 ea df |..c.Pj...vS....| diff --git a/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 b/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 index b524ef43d29..38382edbea7 100644 --- a/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 +++ b/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,117 +7,118 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 28 10 3b 44 b1 |....z...v..(.;D.| -00000010 0f a9 77 89 f9 dd 3c 3a ad 83 a0 ca 3e 60 d6 0e |..w...<:....>`..| -00000020 ab 94 3a ec 2e 63 ef b1 41 90 48 20 00 00 00 00 |..:..c..A.H ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 72 63 6c 83 50 |....z...v..rcl.P| +00000010 e9 4c 88 85 70 4f e3 cb c7 0e 0c c5 e5 44 b9 7e |.L..pO.......D.~| +00000020 4a 88 d3 32 d2 37 5c 16 d4 a1 e5 20 00 00 00 00 |J..2.7\.... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 d9 |..+.....3.$... .| -00000060 ce 37 c6 7e 9c 0f 75 bb b6 91 c9 af 59 eb 24 07 |.7.~..u.....Y.$.| -00000070 2e 80 3a 7e d2 fc 39 9e 45 19 94 2d ae 33 2c 14 |..:~..9.E..-.3,.| -00000080 03 03 00 01 01 17 03 03 00 17 c6 b7 f1 35 ee 93 |.............5..| -00000090 75 ca 2e 3a a2 3d ed 32 5c e1 2c e0 5b 1c 01 e0 |u..:.=.2\.,.[...| -000000a0 bb 17 03 03 00 42 02 e5 db dc 80 e1 c2 6f 31 1c |.....B.......o1.| -000000b0 33 7b 76 8f 51 9c f8 a8 b0 1b 1a 8a 46 00 c7 ff |3{v.Q.......F...| -000000c0 ff 4c c9 d8 28 14 32 74 ee 59 b3 15 4b 45 90 b6 |.L..(.2t.Y..KE..| -000000d0 da 56 b3 ef d4 6f 8a eb 96 b9 94 ab b9 9e b1 2e |.V...o..........| -000000e0 fe 29 f2 0d 0d 93 66 1a 17 03 03 02 6d 84 4e 43 |.)....f.....m.NC| -000000f0 92 85 d5 e0 7a cd da a6 c0 5a bf 8b eb 83 db a0 |....z....Z......| -00000100 dc c3 e2 a8 d5 ca ad 87 75 19 08 dd 3e 2e 36 a0 |........u...>.6.| -00000110 a1 53 28 09 cd 1c 1d a0 24 77 e3 e6 4d b1 8f 36 |.S(.....$w..M..6| -00000120 43 29 79 b3 e2 fb 9e dc 39 90 b5 b7 db 6d 0a c0 |C)y.....9....m..| -00000130 55 d2 1c fd 8d 57 5b bf e3 70 b7 6a bc af 4f 34 |U....W[..p.j..O4| -00000140 e7 e1 46 d3 9a cc e4 73 33 fb e6 ad f9 b5 35 af |..F....s3.....5.| -00000150 97 77 88 11 19 7c e6 7d 8b 08 bb 78 2c 50 29 0c |.w...|.}...x,P).| -00000160 87 5f ef 04 19 34 9f 59 54 df 14 71 d1 5f e7 dc |._...4.YT..q._..| -00000170 46 2e 73 1a 07 12 be 6e 74 e1 8e 82 ca db a2 6d |F.s....nt......m| -00000180 35 5b fc 4c 71 42 45 86 35 1c c0 dc 0d 4c 40 a8 |5[.LqBE.5....L@.| -00000190 c7 ea 4a b8 33 0b 30 e2 6d a4 82 dc 28 35 1f f2 |..J.3.0.m...(5..| -000001a0 ac 23 41 10 a4 d4 1a 40 28 4d ea db 32 d5 06 de |.#A....@(M..2...| -000001b0 1e 37 91 77 34 ed b4 c8 f2 1c 44 de ee 2f dd af |.7.w4.....D../..| -000001c0 61 cc 1e 59 87 a6 be 36 b0 8e a3 61 01 aa f4 60 |a..Y...6...a...`| -000001d0 1e c8 3a 3c 53 57 31 28 3e 40 32 95 67 02 41 9c |..:@2.g.A.| -000001e0 58 28 50 51 5e 06 1d f1 57 e1 39 ba e0 ab 30 26 |X(PQ^...W.9...0&| -000001f0 25 fe b6 0a a9 d5 b3 72 61 3a 71 ec a2 44 91 5e |%......ra:q..D.^| -00000200 30 1b d4 dd 07 cf 35 6a 85 4a 95 b2 a9 f5 5c 6e |0.....5j.J....\n| -00000210 35 f9 07 7b d9 b0 a5 64 2f c3 34 23 84 3f 1a 97 |5..{...d/.4#.?..| -00000220 dd 25 75 7c 76 0f 9b 73 5b aa c0 a1 00 4b f6 b1 |.%u|v..s[....K..| -00000230 61 34 51 d0 d1 3b 00 4f 87 93 f5 45 2e 23 93 ee |a4Q..;.O...E.#..| -00000240 e6 ce e5 1c 02 22 3c c1 22 ed 33 b2 71 99 52 26 |....."<.".3.q.R&| -00000250 70 86 ad bc 41 d9 13 54 d3 3e 5d 4b 63 4d d2 6f |p...A..T.>]KcM.o| -00000260 bf a5 24 f8 7b 83 b2 0b 13 02 0d 42 74 9b 04 4e |..$.{......Bt..N| -00000270 8a 86 6b 40 92 42 3a d8 a8 21 2f ce e0 90 71 65 |..k@.B:..!/...qe| -00000280 5f ed c7 65 38 e3 85 e2 32 d5 4b c0 84 61 24 a1 |_..e8...2.K..a$.| -00000290 00 be 67 f3 59 b0 b2 f0 65 fe a6 49 19 41 f9 9b |..g.Y...e..I.A..| -000002a0 40 3a 62 ec 4d 1f 83 77 03 9d 4b 4c d2 5d 93 ca |@:b.M..w..KL.]..| -000002b0 01 39 44 dc c6 f7 18 6b 2a c9 1b 3d ef 27 6d a4 |.9D....k*..=.'m.| -000002c0 2e 8f 33 63 2b c5 fb bb 52 23 68 7e 0b 16 92 64 |..3c+...R#h~...d| -000002d0 d9 72 04 2d 0d b2 ba 67 45 ae 14 16 f1 57 3b 59 |.r.-...gE....W;Y| -000002e0 44 ba db b0 c9 d2 9b 8f 6d b2 a4 8c c2 d1 1c e4 |D.......m.......| -000002f0 ce d3 32 bf 04 d9 09 d1 28 3d 25 2d b5 d3 da 12 |..2.....(=%-....| -00000300 77 01 45 09 08 e0 df cc f3 4c c0 e0 b7 d7 d8 16 |w.E......L......| -00000310 82 19 1d 57 dc b4 27 83 48 1b 9f a9 0e cc d6 39 |...W..'.H......9| -00000320 c1 4a 66 b3 42 85 a5 a7 14 97 5c 58 fe 41 e1 2e |.Jf.B.....\X.A..| -00000330 16 e9 70 89 e7 98 a8 f3 4a 81 d4 d8 ff 5f 48 6e |..p.....J...._Hn| -00000340 60 c6 4a 07 c5 57 9c 22 25 3a 9f bf 7e 71 f3 0d |`.J..W."%:..~q..| -00000350 71 e5 a5 d4 2b 6d 70 2f c5 a3 17 03 03 00 99 b9 |q...+mp/........| -00000360 15 c7 70 bc 06 75 26 50 0f 22 90 43 99 25 0d 0f |..p..u&P.".C.%..| -00000370 05 d3 ce e7 3c 53 fb 01 d4 d2 e8 fb b7 49 87 03 |....K......#..._C.| -000003e0 75 65 ac ba 46 43 61 b4 3d be b8 49 44 ad 15 00 |ue..FCa.=..ID...| -000003f0 3b c0 07 ba 18 b2 14 71 17 03 03 00 35 d1 22 81 |;......q....5.".| -00000400 7f 21 e9 e2 7b 11 f5 df dd 3f 15 ce b5 fc 71 f3 |.!..{....?....q.| -00000410 0e f2 d0 1c a4 85 29 88 f2 ca 73 01 ee 1c e4 66 |......)...s....f| -00000420 07 fa 5c a3 32 b0 e4 2a e4 97 e5 70 b1 cd db 79 |..\.2..*...p...y| -00000430 83 1f |..| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 d7 |..+.....3.$... .| +00000060 fa 97 47 72 9a 7e 63 47 d6 62 2d dc 5d 4f 7f 9b |..Gr.~cG.b-.]O..| +00000070 aa 86 c9 ba 65 4c ae 91 82 40 38 ad 4b 46 73 14 |....eL...@8.KFs.| +00000080 03 03 00 01 01 17 03 03 00 17 27 2e 49 01 db 5e |..........'.I..^| +00000090 e1 45 48 97 54 02 31 9f ad 62 74 58 70 77 21 5b |.EH.T.1..btXpw![| +000000a0 81 17 03 03 00 42 2c 0a 8a a0 e0 40 32 b1 2f 9f |.....B,....@2./.| +000000b0 e6 13 9f fd 62 88 a7 34 bd 9a bc 64 5d 9d 17 b9 |....b..4...d]...| +000000c0 b0 f6 fc 84 ca 3f 80 0b 97 4f 7a d9 67 42 c5 0a |.....?...Oz.gB..| +000000d0 e5 18 21 e8 08 42 b4 e6 f5 7e c3 70 2c 0e d3 d8 |..!..B...~.p,...| +000000e0 15 36 37 57 1a d5 58 64 17 03 03 02 6d 07 11 32 |.67W..Xd....m..2| +000000f0 d3 1e 03 02 fb 04 35 f2 64 a8 78 c2 b2 f7 7d 5c |......5.d.x...}\| +00000100 7c 94 0c 7b 16 9a 87 7d 2f 96 de 01 74 d6 6c 6f ||..{...}/...t.lo| +00000110 ce 95 eb f0 df 6d 52 89 3a 19 ff 5b b5 f2 d8 6d |.....mR.:..[...m| +00000120 e6 10 94 f7 d9 c4 58 e8 80 db f5 30 22 b1 82 b1 |......X....0"...| +00000130 66 05 b5 d0 71 40 0f 68 83 ec 43 b5 51 c3 f8 ce |f...q@.h..C.Q...| +00000140 e9 71 4a c7 cf 57 b5 53 3f 60 99 ae 84 df 98 cc |.qJ..W.S?`......| +00000150 9f 90 d0 fc 1d 03 e9 80 72 7c 60 51 a1 89 93 6d |........r|`Q...m| +00000160 0a 57 18 c6 dc 22 82 71 be 66 87 93 dd 16 41 c8 |.W...".q.f....A.| +00000170 84 38 33 63 fc 82 db 38 63 f8 84 f7 12 08 3b 82 |.83c...8c.....;.| +00000180 18 cb c0 50 0d dd 19 25 16 88 23 97 35 56 6d 46 |...P...%..#.5VmF| +00000190 3d 75 e1 83 c3 62 e4 19 70 6c 03 f0 33 5d 94 ad |=u...b..pl..3]..| +000001a0 6d be d2 db c4 b8 ad d8 78 78 53 76 62 91 f7 cf |m.......xxSvb...| +000001b0 83 5b 1e 44 11 2f 27 6a 29 d4 ea 96 fb 40 1c 94 |.[.D./'j)....@..| +000001c0 69 c2 cc c7 90 2c 60 14 c7 d4 f2 9c f9 0e 66 1c |i....,`.......f.| +000001d0 08 76 6e 9f 3b 3a 47 8a 40 0a de 00 e4 6f 45 ca |.vn.;:G.@....oE.| +000001e0 1d 41 cc 34 5a 2c 67 78 58 34 eb 19 0c a5 0e a2 |.A.4Z,gxX4......| +000001f0 fb c1 0a 25 74 f5 ec 55 f8 c3 97 00 d0 a5 90 c5 |...%t..U........| +00000200 a1 9c aa 19 2b e6 ee c1 9d 73 a1 3c 1f fa 6a 91 |....+....s.<..j.| +00000210 2b 2d 27 be 06 f3 85 54 63 a5 d9 ac 55 73 0a e4 |+-'....Tc...Us..| +00000220 4f dc 25 a0 9f 39 c0 0e 1a 9d a7 4c bd c9 3c 64 |O.%..9.....L..>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 01 50 dd d8 5d 40 64 |..........P..]@d| -00000010 5d 35 b0 82 0d 46 97 4c a2 d1 4d dd 3c c9 0a f9 |]5...F.L..M.<...| -00000020 39 6a 1c 17 c3 f6 1a 6b 42 cc f7 37 23 7a e1 bf |9j.....kB..7#z..| -00000030 de 51 7f 87 6b 3d d6 4d ed 24 b3 de dd 62 18 4a |.Q..k=.M.$...b.J| -00000040 b5 b3 1e 0f 2f a3 c5 e8 67 65 04 bc 37 97 15 a8 |..../...ge..7...| -00000050 a8 f3 a8 79 99 82 e1 10 5d d7 f2 ee 21 46 aa b8 |...y....]...!F..| -00000060 40 9f 3b fc 12 19 c8 82 b4 8e bc b8 9b a9 f6 aa |@.;.............| -00000070 18 6b 48 4e 03 92 43 12 b8 54 f2 b7 29 0b 0a a1 |.kHN..C..T..)...| -00000080 6f c4 1c 2a af 22 c1 3d 1b 43 a5 3c 7d 39 83 5d |o..*.".=.C.<}9.]| -00000090 ee 09 fb f1 9a 4c ff b3 2a bb 85 53 04 18 5e 18 |.....L..*..S..^.| -000000a0 62 e8 cf ec 01 be 76 31 82 1a 60 19 33 c7 37 0a |b.....v1..`.3.7.| -000000b0 fa 45 4d b1 9a 1e 07 e9 9c 45 c3 89 60 a2 c9 59 |.EM......E..`..Y| -000000c0 8c 7d 02 f6 d6 5c 12 26 bd 6d 97 15 e2 07 27 be |.}...\.&.m....'.| -000000d0 2f 59 93 1b 11 0e 05 ef 83 c6 a2 c0 1a 9a 4c 60 |/Y............L`| -000000e0 a6 84 c0 72 b6 2b 7c a1 37 4c d7 eb 76 0f 00 97 |...r.+|.7L..v...| -000000f0 43 b6 25 ed 36 e1 eb 3a 3d 71 05 d8 d0 f9 80 18 |C.%.6..:=q......| -00000100 b2 9b c0 4e 2c 8e 05 41 52 a5 40 57 3c 1f 48 0c |...N,..AR.@W<.H.| -00000110 55 ea d3 76 6d 3a 26 5d 5d 71 74 1c d5 8d 96 92 |U..vm:&]]qt.....| -00000120 79 c5 9c 78 68 5f 20 12 01 06 c3 52 49 66 e4 5b |y..xh_ ....RIf.[| -00000130 41 09 fa 72 c5 d7 d9 26 1b fa a5 1d 23 b2 4a 1e |A..r...&....#.J.| -00000140 da 83 5e 89 c8 3a c4 26 f2 42 70 6d 1b 90 67 eb |..^..:.&.Bpm..g.| -00000150 37 15 35 b9 a2 b0 2b ef 93 5f 11 17 03 03 00 59 |7.5...+.._.....Y| -00000160 b4 a0 79 ba e4 3f 78 d2 11 1a 71 8a a1 a4 28 fc |..y..?x...q...(.| -00000170 44 c7 bc 32 19 06 71 1b 6d 50 20 26 d5 91 39 48 |D..2..q.mP &..9H| -00000180 59 8b fd 55 0a 35 14 f5 31 47 62 15 ee c1 69 23 |Y..U.5..1Gb...i#| -00000190 eb db 79 ef 20 47 5c ef 31 e1 ae bd 2f 72 f8 9d |..y. G\.1.../r..| -000001a0 92 cc 04 6f 73 22 5d 93 59 9f 06 cb bd 70 9b d8 |...os"].Y....p..| -000001b0 c9 41 44 8f 5b b2 59 2b a9 17 03 03 00 35 22 65 |.AD.[.Y+.....5"e| -000001c0 ef 1e dc 4c 63 ba 6d 6a 46 1c d2 9c 9a 81 4b f3 |...Lc.mjF.....K.| -000001d0 1f 58 4e 08 86 93 f8 3a 53 13 64 1f ca 20 d2 da |.XN....:S.d.. ..| -000001e0 6b df 54 88 a8 f3 af 0d 4a 1b 29 91 3a bb 90 27 |k.T.....J.).:..'| -000001f0 29 3a 97 17 03 03 00 17 09 78 1d f3 95 2e 92 af |):.......x......| -00000200 d8 af 64 59 fb 77 e3 85 de f0 37 be 11 91 2f 17 |..dY.w....7.../.| -00000210 03 03 00 13 4e a2 06 c3 90 6f d3 b0 04 a8 25 32 |....N....o....%2| -00000220 09 65 1c f2 ef 9c 32 |.e....2| +00000000 14 03 03 00 01 01 17 03 03 01 50 90 77 22 64 76 |..........P.w"dv| +00000010 a1 cd 65 49 53 cb f0 2e 21 6c 12 7c 63 e5 ff 49 |..eIS...!l.|c..I| +00000020 6c be e6 ba 70 2d 22 49 6e 5c 5b 65 46 4b 64 01 |l...p-"In\[eFKd.| +00000030 f7 1d 57 a3 5f d5 a3 39 b6 b9 79 62 b3 e2 52 35 |..W._..9..yb..R5| +00000040 95 26 d9 2b 72 39 60 23 c4 5f 7e 88 66 d4 c8 2b |.&.+r9`#._~.f..+| +00000050 2d 89 38 c8 b8 bd 73 0a 02 27 92 ab 89 8a ee 9b |-.8...s..'......| +00000060 a2 bc 9e 55 fd a0 d4 f3 02 d7 d6 4c 6c 49 ef 7e |...U.......LlI.~| +00000070 35 56 90 41 90 53 24 f5 c1 19 f0 ff a0 c8 7c 82 |5V.A.S$.......|.| +00000080 52 01 98 8c ef 87 69 09 d2 17 35 af 9c 4b 3b b3 |R.....i...5..K;.| +00000090 6c 36 70 63 48 a2 88 df cb 87 f3 40 03 a8 b0 64 |l6pcH......@...d| +000000a0 cc 66 fb cf ba b9 be 8c 67 2d 3c 99 ac 7f 93 c1 |.f......g-<.....| +000000b0 15 2e 05 ae 95 51 3d 71 d9 43 09 d7 44 cb df 67 |.....Q=q.C..D..g| +000000c0 b8 b3 33 62 c5 60 cf 22 20 e5 45 17 7c d6 74 12 |..3b.`." .E.|.t.| +000000d0 0f 6d af d0 db dd 91 ad 20 ea 4d 26 fc c4 2b bd |.m...... .M&..+.| +000000e0 ec 3d 75 c8 87 36 b2 d0 1e cc 1d 92 fd 58 5e d5 |.=u..6.......X^.| +000000f0 f7 ad c2 ed 0c b6 c6 bc 25 ff 39 75 ee cf fc 76 |........%.9u...v| +00000100 77 e0 15 2e 22 82 3b 6f 93 e4 e9 a1 5a bb 9d 78 |w...".;o....Z..x| +00000110 e2 3d 18 c8 e5 ea e3 82 52 de bf ca 32 c9 56 21 |.=......R...2.V!| +00000120 ba c9 2b 12 7d 7b f5 18 73 e5 5e 9c 1e e1 23 92 |..+.}{..s.^...#.| +00000130 ec 58 56 e5 a4 aa dc 2b 59 75 71 19 06 77 83 d7 |.XV....+Yuq..w..| +00000140 0b 28 03 e9 fa 2c 89 1a 8c 64 f0 84 b6 13 f0 02 |.(...,...d......| +00000150 22 02 33 cf c4 22 dd fb b0 76 8a 17 03 03 00 59 |".3.."...v.....Y| +00000160 9b 4c 67 95 f4 37 c9 2c b7 33 c7 78 1c e0 1b 49 |.Lg..7.,.3.x...I| +00000170 41 6f 88 2d 99 a7 e3 d3 d1 d1 f6 36 b1 2a 8e df |Ao.-.......6.*..| +00000180 11 b6 8d 04 63 c7 11 49 e2 8c 79 03 6b b8 a4 8b |....c..I..y.k...| +00000190 2a 2c 04 ab b3 e2 50 03 51 77 65 eb 3a 45 f1 ce |*,....P.Qwe.:E..| +000001a0 65 9f 9c be d6 be 7f 28 14 6a 61 37 55 94 8f a7 |e......(.ja7U...| +000001b0 23 2f bc fc bb aa 89 47 76 17 03 03 00 35 f5 be |#/.....Gv....5..| +000001c0 e6 33 9b 48 97 74 b0 ad a4 fc 78 fe 20 ab cd fa |.3.H.t....x. ...| +000001d0 48 ad 8c 55 c3 46 b8 2e d6 ea f0 79 e3 a5 cf 29 |H..U.F.....y...)| +000001e0 56 19 ab 95 c4 7f fd 89 41 f7 a3 6f e4 19 2f 83 |V.......A..o../.| +000001f0 8c 3e 5d 17 03 03 00 17 74 24 c5 8d 30 40 0a 12 |.>].....t$..0@..| +00000200 57 37 d0 27 30 3e 24 ea 81 ca c7 0a f5 12 cf 17 |W7.'0>$.........| +00000210 03 03 00 13 ff 20 1a 76 60 da a1 15 22 16 10 8a |..... .v`..."...| +00000220 9f e1 ee 5d 62 a2 cc |...]b..| diff --git a/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA b/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA index 0cd5b76d660..10c83c4828d 100644 --- a/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA +++ b/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,129 +7,130 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 40 ad 79 0c ad |....z...v..@.y..| -00000010 83 38 58 82 dc b2 5a d1 e2 de f5 43 99 72 8a 93 |.8X...Z....C.r..| -00000020 ba b1 ea 17 21 52 a7 e9 ed dc 48 20 00 00 00 00 |....!R....H ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 af 7e fd 3d 23 |....z...v...~.=#| +00000010 96 b6 46 26 9c 09 13 f6 80 4f c9 d2 52 d9 df 52 |..F&.....O..R..R| +00000020 0b 7c da 61 52 ba 99 1b 32 5a 0c 20 00 00 00 00 |.|.aR...2Z. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 bd |..+.....3.$... .| -00000060 d2 3a 7e c2 30 84 4f f2 39 7e 26 11 65 49 b9 b2 |.:~.0.O.9~&.eI..| -00000070 ac 63 c8 ef ea 5e f6 23 33 70 ec 16 86 49 03 14 |.c...^.#3p...I..| -00000080 03 03 00 01 01 17 03 03 00 17 16 47 c1 58 83 6b |...........G.X.k| -00000090 66 06 c4 39 42 8f 68 fb 3a 07 9e e7 74 41 0d 10 |f..9B.h.:...tA..| -000000a0 97 17 03 03 00 42 42 b2 84 94 a6 18 c6 b6 21 77 |.....BB.......!w| -000000b0 1e 02 57 4a 14 2d c4 84 17 f1 fa b4 63 0f aa d7 |..WJ.-......c...| -000000c0 4a d5 ae 75 f1 da 14 ec 51 09 93 6b 62 6f 8f 7e |J..u....Q..kbo.~| -000000d0 fe 0c 7f 63 ef 1b 87 d8 43 42 d0 f4 2d 6d 0f cc |...c....CB..-m..| -000000e0 ef 77 79 17 1e 39 1e 75 17 03 03 02 22 9c 82 27 |.wy..9.u...."..'| -000000f0 99 e0 4b 44 a7 a7 bb a9 25 a2 58 7f 70 3f 82 1a |..KD....%.X.p?..| -00000100 4b bc e1 35 3e 66 fa 4f ac 7f 7e da 73 13 06 0f |K..5>f.O..~.s...| -00000110 fe 97 ef 82 53 2e d0 e2 11 c6 ee 8d 25 d2 f0 5c |....S.......%..\| -00000120 2e b8 61 40 09 12 d4 11 9b b8 3d 38 d7 d5 a7 76 |..a@......=8...v| -00000130 ed a7 bf 6f 39 9c 83 49 57 86 de 53 da c5 ff 8a |...o9..IW..S....| -00000140 ee 47 bc 19 72 d3 cc d0 5b fc 6b 25 2f 64 2a 0c |.G..r...[.k%/d*.| -00000150 7d e9 8a 1f f8 48 d1 74 d5 70 97 e7 b4 e2 c8 ce |}....H.t.p......| -00000160 dc 74 27 e9 af b1 64 56 19 28 8a 34 93 4e 1c 03 |.t'...dV.(.4.N..| -00000170 67 ae 41 fb 5f d1 e3 20 45 6b bd 49 25 d8 b4 8b |g.A._.. Ek.I%...| -00000180 d4 96 d6 96 b2 72 72 f0 d0 68 f1 f7 f3 17 76 85 |.....rr..h....v.| -00000190 78 0e dd 35 83 8a 7a 45 c5 91 86 4b a6 b5 77 b4 |x..5..zE...K..w.| -000001a0 ef 02 43 5c 42 c7 f8 a6 1d ed 73 d2 41 02 be cb |..C\B.....s.A...| -000001b0 24 40 61 5a 5f 7a f6 bf f9 d0 bd 05 7f 90 52 16 |$@aZ_z........R.| -000001c0 65 49 c6 74 61 f0 05 fa dd 83 69 b7 ff 5a 2c 4b |eI.ta.....i..Z,K| -000001d0 63 6d d2 57 01 43 67 54 25 90 72 f8 12 7e c2 39 |cm.W.CgT%.r..~.9| -000001e0 26 a9 65 55 02 ca 87 8a e6 13 cd a4 6b eb 3c 4d |&.eU........k.#| -00000250 59 38 6c 9f be 1b ba 60 93 e8 c9 24 fb 13 11 b7 |Y8l....`...$....| -00000260 78 d8 a7 30 6d 06 0f 4d 59 5d d1 1f 81 13 33 99 |x..0m..MY]....3.| -00000270 a8 4d 63 16 53 73 40 22 4b 55 21 79 c1 ce 1c 92 |.Mc.Ss@"KU!y....| -00000280 8c d6 95 14 fd 93 5d c2 54 20 30 c5 79 b0 cd eb |......].T 0.y...| -00000290 ac 1b 50 6a 25 b7 e8 f1 0f da f3 d8 6b 17 2b 12 |..Pj%.......k.+.| -000002a0 06 a8 9a 88 be 2f f3 52 b3 d7 70 05 df 57 88 f9 |...../.R..p..W..| -000002b0 ec 59 d4 e7 ce cb c3 1f 33 3e c0 d8 04 9f 59 a0 |.Y......3>....Y.| -000002c0 04 c0 13 b3 a6 7c ce 6c c4 fa 82 cd da 11 17 b6 |.....|.l........| -000002d0 c2 40 cd e6 5a 6e d3 b5 17 f0 4d c4 34 8f 2a 28 |.@..Zn....M.4.*(| -000002e0 4d ce 93 d5 eb 7e 0a d2 57 0a 98 cf ac 48 ee a8 |M....~..W....H..| -000002f0 8a bd ec c2 d7 d9 39 af e2 a0 9f b2 fd d1 4e 96 |......9.......N.| -00000300 fa fd 34 f7 a4 3e 3d 31 9a f6 a2 a7 97 a3 43 17 |..4..>=1......C.| -00000310 03 03 00 a4 cf 0d e1 8d b7 e4 1a c0 79 0d 7e d9 |............y.~.| -00000320 70 a3 34 57 0f 72 b4 5c 05 7f 1e 16 52 ba d3 e7 |p.4W.r.\....R...| -00000330 fb e5 b8 b0 8d cf 91 7e 96 c4 70 6e cb e5 7e 51 |.......~..pn..~Q| -00000340 19 17 c1 94 e9 49 69 a0 21 59 74 a9 1d 34 9c 10 |.....Ii.!Yt..4..| -00000350 a9 10 f0 4a 51 2c e3 1d e3 59 28 f2 3b ea 66 c1 |...JQ,...Y(.;.f.| -00000360 ed 6a 8d 39 72 ea 5a 24 7a ee 9f cd 85 9d 54 60 |.j.9r.Z$z.....T`| -00000370 d4 95 fd 8d 63 a4 78 6c 2f 7d 6a a5 53 e4 42 97 |....c.xl/}j.S.B.| -00000380 e8 19 36 bf 14 9c a8 48 9f 57 ad 29 7a 30 e5 a9 |..6....H.W.)z0..| -00000390 32 e7 0f 24 9c ca 9d 6d b7 47 46 1c cb 90 7d 18 |2..$...m.GF...}.| -000003a0 39 70 d2 c1 08 28 dc d7 3a 3e 5e 62 a7 4a 4a af |9p...(..:>^b.JJ.| -000003b0 02 93 ce 4b 5d a2 96 f3 17 03 03 00 35 10 07 d6 |...K].......5...| -000003c0 82 f3 28 ef 2f 08 17 f6 0b c2 da 1f b7 52 e1 eb |..(./........R..| -000003d0 ca f4 0b c6 21 5c 54 4d f9 0b 04 c1 5a bf 63 58 |....!\TM....Z.cX| -000003e0 1c e1 da 7f f7 1f 84 77 09 3a 35 7c e6 1f 89 f2 |.......w.:5|....| -000003f0 fd 01 |..| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 83 |..+.....3.$... .| +00000060 95 cf ff 0f f6 eb 66 dc 4f 61 f3 94 43 18 7b f5 |......f.Oa..C.{.| +00000070 91 6a e5 36 75 7b 6b 2c d4 38 f7 4f 36 f0 3c 14 |.j.6u{k,.8.O6.<.| +00000080 03 03 00 01 01 17 03 03 00 17 b7 83 3c 5c 9e ee |............<\..| +00000090 fc c3 14 33 45 62 69 8b 63 25 03 77 fe 7c 8b c0 |...3Ebi.c%.w.|..| +000000a0 0a 17 03 03 00 42 6c cd df 26 24 42 0d 2e 38 64 |.....Bl..&$B..8d| +000000b0 c5 92 7c 6b 18 47 cc 90 09 57 95 0a f9 cc 81 f1 |..|k.G...W......| +000000c0 db 90 29 ba b0 3f db 99 55 78 93 ab 05 34 91 46 |..)..?..Ux...4.F| +000000d0 ce cb c5 2c b8 fb 43 98 31 cc 18 8f 2e 2a 39 78 |...,..C.1....*9x| +000000e0 68 6d 01 29 05 ff 7e 4f 17 03 03 02 22 c1 3d c5 |hm.)..~O....".=.| +000000f0 cb 42 fe 5d a8 ea 65 fd 1a a8 cd a9 28 ed 8d 69 |.B.]..e.....(..i| +00000100 5b eb 28 11 c5 bb 9f 58 8d f2 2d 44 b4 8f 87 d6 |[.(....X..-D....| +00000110 3f af df 3f 13 c0 7e bf 6f b3 e0 fa 45 5c ee a2 |?..?..~.o...E\..| +00000120 13 70 08 94 2d 87 a7 1c 23 a9 aa a1 64 d2 49 ed |.p..-...#...d.I.| +00000130 33 2c ae 02 9e a7 03 24 3f 4c 43 d4 2e 54 b9 fc |3,.....$?LC..T..| +00000140 39 6c 32 8c b1 0c bb f6 31 60 d9 48 82 5b ed 2b |9l2.....1`.H.[.+| +00000150 ea dd e3 2d 1a 35 a3 22 be e1 f1 13 04 9c aa 1a |...-.5."........| +00000160 24 39 4a 0d 63 fb ce 31 71 af e6 1c f3 a3 dd c1 |$9J.c..1q.......| +00000170 51 40 28 5a 11 a0 9e 19 0a a5 74 e2 40 56 9c 55 |Q@(Z......t.@V.U| +00000180 40 45 e6 20 5d 23 aa 85 ec 42 5f 2c 24 10 fb ff |@E. ]#...B_,$...| +00000190 8a 52 e6 33 8f e1 1e e1 51 8a 9f 5d 6f 63 b8 04 |.R.3....Q..]oc..| +000001a0 13 ab fa 5d 85 ba d3 eb cf b9 0b 89 08 b7 7b a9 |...]..........{.| +000001b0 ea 07 b9 41 07 7a 08 7b 57 01 35 11 a1 65 99 4a |...A.z.{W.5..e.J| +000001c0 4c 4a 1f c2 94 5a 00 09 9a 13 37 23 16 60 45 62 |LJ...Z....7#.`Eb| +000001d0 96 fa 6b 7a 0f d6 68 14 f5 cd 40 d7 0a eb ea 75 |..kz..h...@....u| +000001e0 f0 29 cb ea 7f e7 55 36 d9 02 b2 a0 bc 54 ac 04 |.)....U6.....T..| +000001f0 1b 00 10 c0 db 45 81 e6 97 2a 4a 57 1d e7 de e3 |.....E...*JW....| +00000200 d1 0a 09 c7 73 6a 9e a0 3c 79 7f a8 26 6a 98 05 |....sj..B ]^..| +000003f0 a3 91 |..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 11 f1 43 fc 28 7d |............C.(}| -00000010 43 0b 17 e4 ed cc 95 d5 09 4e 8f 44 3c 3b 46 23 |C........N.D<;F#| -00000020 59 a4 62 a7 94 1e da b6 a7 a5 22 15 6a ed e3 eb |Y.b.......".j...| -00000030 4f 6d 0e 91 c6 20 74 af 97 80 95 db 6a b6 2d ac |Om... t.....j.-.| -00000040 a8 d9 95 84 95 5b 32 27 ec 42 42 a8 fd 05 fc ad |.....[2'.BB.....| -00000050 2e 00 e3 4a 9d 93 d1 5e fd dc 22 30 1f 9c e9 cb |...J...^.."0....| -00000060 3f 2e ac ad 0f ab b7 46 82 69 38 db c6 8a be 77 |?......F.i8....w| -00000070 7e 83 77 4c e1 f4 f2 cf c2 b1 86 ff 17 d3 1d 79 |~.wL...........y| -00000080 3e ac f8 6e 73 15 ab 02 4c bf 2a 63 41 ce 93 3b |>..ns...L.*cA..;| -00000090 af 11 70 8c 91 91 f4 14 5c 1b 63 4b 42 3b d8 ca |..p.....\.cKB;..| -000000a0 00 f6 02 b3 c8 d3 ab 01 1d f2 71 86 7b f9 13 de |..........q.{...| -000000b0 1e 39 1c e7 b5 3b b5 bb 26 33 f7 a9 3f 29 e2 8c |.9...;..&3..?)..| -000000c0 d1 67 64 11 b4 29 be 6e c9 cf c5 6e 41 43 41 e7 |.gd..).n...nACA.| -000000d0 43 9c 5d fb a1 b6 b3 f9 0f 4c 17 11 3c 56 0e 49 |C.]......L...z.U.....4..| -00000130 11 86 8a 14 8e d6 5c c0 c2 55 de da 37 c4 ac 69 |......\..U..7..i| -00000140 95 42 84 5f 1d 5f c7 32 91 a9 45 02 c3 a3 da 4f |.B._._.2..E....O| -00000150 96 da c0 a2 09 7a a6 2b 25 f4 a2 94 89 fa bd 0f |.....z.+%.......| -00000160 87 04 e1 87 00 c4 4f 45 39 7a 5a 7d 75 c5 c9 f6 |......OE9zZ}u...| -00000170 27 34 2d ba 12 c5 2c 76 06 b0 aa d0 34 e1 99 e9 |'4-...,v....4...| -00000180 9b 01 db 2a b4 d5 dd 55 2b 92 6d e3 9e fc f1 09 |...*...U+.m.....| -00000190 2b 37 8b 37 8f 70 31 ee d2 f0 86 5a 1f d3 4a 29 |+7.7.p1....Z..J)| -000001a0 7c c9 0e 97 7c 4f e6 87 b7 c8 94 f3 d2 0b 4a 1d ||...|O........J.| -000001b0 59 60 09 81 55 6a 01 38 9f ca 20 e0 6e 44 f7 b5 |Y`..Uj.8.. .nD..| -000001c0 f6 3e 2e d0 81 f6 e6 1d 15 cf c3 d8 ae 98 84 d1 |.>..............| -000001d0 0b c9 e4 65 96 f9 eb c9 60 6d 50 37 49 9f 6d b1 |...e....`mP7I.m.| -000001e0 b9 f6 25 20 81 2d cf b4 17 2b 4c a9 8a 76 8a db |..% .-...+L..v..| -000001f0 77 8c 29 47 05 0b 27 e1 52 8d 37 27 fb c0 70 26 |w.)G..'.R.7'..p&| -00000200 3b 6d 2e 74 05 75 88 e4 63 3d ac 98 3f 74 67 3b |;m.t.u..c=..?tg;| -00000210 c6 dc 41 39 2b 20 ef f9 8b 2f 4e 20 17 03 03 00 |..A9+ .../N ....| -00000220 99 7d 8a 83 dd 34 5e 37 e2 c3 85 22 f3 6b ee bc |.}...4^7...".k..| -00000230 a5 21 1b c5 2c 38 cf 99 09 5b 31 97 5e a0 8b 69 |.!..,8...[1.^..i| -00000240 75 3a 23 64 18 22 fb 31 ed ac 8b 0f ae 9c 4e ee |u:#d.".1......N.| -00000250 06 0e 3c 3a 18 d3 8e 0c dc d4 3f 7b 25 e3 90 85 |..<:......?{%...| -00000260 ca f4 8a 5c 5e 5e 44 f3 1b 57 cd 14 e0 8d 67 36 |...\^^D..W....g6| -00000270 6e c2 a6 95 60 f3 86 20 29 a6 a8 8f b3 b0 0d 57 |n...`.. )......W| -00000280 d2 1e 4a b9 d2 63 33 09 f9 c5 87 94 89 c5 fd 2e |..J..c3.........| -00000290 de b3 f0 0e 7b 4e 3e d6 21 b4 3b 58 bd 2a 35 49 |....{N>.!.;X.*5I| -000002a0 5e b0 f4 5a ca 58 dc a5 8b 45 a5 d1 7b 13 b2 00 |^..Z.X...E..{...| -000002b0 52 c4 b2 6c d1 9a b8 c5 1b fe 17 03 03 00 35 c9 |R..l..........5.| -000002c0 9b c7 94 b3 eb 5f 4e ab 8c c0 de cf b6 b4 5c ee |....._N.......\.| -000002d0 bb 5f fa 48 a2 06 f0 ed f5 b1 ba 74 0c c5 64 1a |._.H.......t..d.| -000002e0 ce 2e 9e 90 4b 6e 98 13 a0 98 99 a3 b4 6f 73 76 |....Kn.......osv| -000002f0 7b e3 26 15 17 03 03 00 17 3e a1 f0 68 e6 00 86 |{.&......>..h...| -00000300 10 f4 bf 26 b6 f5 e6 77 85 ca b7 c1 75 bb f9 78 |...&...w....u..x| -00000310 17 03 03 00 13 43 7f f3 84 ee d7 a9 59 9d c3 5c |.....C......Y..\| -00000320 c0 b7 c8 20 4e 83 ba 23 |... N..#| +00000000 14 03 03 00 01 01 17 03 03 02 11 e0 62 97 8a 4d |............b..M| +00000010 01 cf 8f e2 d2 a8 0d d4 9a fc f5 b2 d7 82 2b 7a |..............+z| +00000020 8c e7 ce 2a 99 3b 41 a2 a3 ca c4 9d 15 79 7f 2f |...*.;A......y./| +00000030 04 7a 18 e4 5b b6 01 d6 b5 03 d2 08 15 41 c7 18 |.z..[........A..| +00000040 8a 66 78 05 ed 33 19 8e 93 9e c3 ff 4a 92 bb 7b |.fx..3......J..{| +00000050 72 e5 81 a6 2a 7f b3 e1 72 67 01 7a 95 f4 3f bc |r...*...rg.z..?.| +00000060 cd e4 bc 45 74 9b 4c 1c 69 68 d0 75 89 9f d5 d0 |...Et.L.ih.u....| +00000070 de 59 d4 1c 47 cc 5e 2e dd bd f9 1f e4 16 c9 c8 |.Y..G.^.........| +00000080 9b 4e 07 6b 7a 12 e7 13 71 ae c1 26 48 32 d6 4e |.N.kz...q..&H2.N| +00000090 8a 15 c2 a0 91 59 9d 21 0d 28 d2 94 3f e9 fc 74 |.....Y.!.(..?..t| +000000a0 98 5b e5 be 50 ad 10 7d d9 a1 da 41 59 15 b3 85 |.[..P..}...AY...| +000000b0 2d 7b 81 b3 ae fb db 4c 00 24 31 57 f2 54 b7 f7 |-{.....L.$1W.T..| +000000c0 64 cc 73 23 bc 6a 93 e0 91 a7 5e 1b 63 f1 59 89 |d.s#.j....^.c.Y.| +000000d0 a9 d9 7b 88 35 17 7a 4d b9 66 d0 a5 f2 d6 79 ed |..{.5.zM.f....y.| +000000e0 c1 3a e7 98 88 96 e7 2f 31 66 bf 16 34 e2 fd 5f |.:...../1f..4.._| +000000f0 fb 0f fb 9a aa ba 78 d8 6a c9 72 d6 39 32 3a 99 |......x.j.r.92:.| +00000100 a2 11 8a 32 79 cf 18 d9 22 da 40 31 3e d3 c8 17 |...2y...".@1>...| +00000110 c4 1f e2 4f c8 7f b9 2f 83 d7 5e 59 48 d3 9b b9 |...O.../..^YH...| +00000120 68 9c c2 e4 45 c2 a3 26 91 cd 3a 26 47 c4 b8 7f |h...E..&..:&G...| +00000130 8f 91 c0 06 b5 6e 5e b4 65 05 42 ea 48 9e 40 bc |.....n^.e.B.H.@.| +00000140 0c 04 22 86 6a 54 6c 27 c3 77 b4 b9 22 99 6a f0 |..".jTl'.w..".j.| +00000150 91 bc 41 ca 24 41 52 fd e2 18 0f 64 13 7e a3 6b |..A.$AR....d.~.k| +00000160 ab 27 1e 15 87 0d 7f 71 1e 29 16 f9 af 81 ec bc |.'.....q.)......| +00000170 28 0b 45 bd 76 fd ff 0e fb 8d c5 0c aa ef a5 17 |(.E.v...........| +00000180 55 49 a6 3d 74 5c 8d 77 60 99 a1 8f aa a9 eb 0f |UI.=t\.w`.......| +00000190 75 1a 55 21 3a 96 da 08 a2 cd ad 11 78 15 6a ce |u.U!:.......x.j.| +000001a0 ef f6 fb 8b a3 dd fd ad 2d a5 2d 59 25 37 fe 53 |........-.-Y%7.S| +000001b0 48 90 fa 9a d3 3c 09 69 47 d3 d1 e4 48 30 fd df |H....<.iG...H0..| +000001c0 15 d7 64 ff ca 91 46 c2 36 82 30 ae 4e 75 12 be |..d...F.6.0.Nu..| +000001d0 58 5d da 63 da bd dc be 81 be ad 37 87 ea 0a 26 |X].c.......7...&| +000001e0 31 cf 1b 1e 7d de a8 04 e3 b8 e5 65 5a 21 db b6 |1...}......eZ!..| +000001f0 2b 7c e7 23 7c 2b e1 89 3f 28 27 97 dd 1c c6 00 |+|.#|+..?('.....| +00000200 0e e4 05 68 0f 9a 8a 1d e6 bd bd aa 1f 46 6e a2 |...h.........Fn.| +00000210 d9 69 91 9b e7 e3 6c 39 33 77 b8 76 17 03 03 00 |.i....l93w.v....| +00000220 99 c9 3e 7e 78 3b 91 65 35 cb 19 44 92 f7 77 f5 |..>~x;.e5..D..w.| +00000230 60 3c 19 2a 97 c5 a0 92 b2 28 e2 44 94 ec 1b 3d |`<.*.....(.D...=| +00000240 f8 1a c1 65 eb 41 3f 61 f1 db 42 1a 0d b8 32 12 |...e.A?a..B...2.| +00000250 f6 1b 83 be 37 d8 fe 78 bd 5b 66 d1 f2 6c 3e e3 |....7..x.[f..l>.| +00000260 8a 0f 3a 28 57 71 1a 78 ab 2a b5 5f ad a3 6e 2c |..:(Wq.x.*._..n,| +00000270 a3 d9 3a 0b d0 99 95 d6 dc 8e 7a f0 b6 e4 cb 46 |..:.......z....F| +00000280 ab cb eb cf ec 86 b3 fe e6 e6 73 2c a2 64 d2 d5 |..........s,.d..| +00000290 9c 8c 25 39 62 07 51 93 12 92 2b e3 4b 2e 3d f5 |..%9b.Q...+.K.=.| +000002a0 f1 d4 22 69 c3 90 cf 91 35 2f e4 60 35 44 6f bf |.."i....5/.`5Do.| +000002b0 7a 75 3d fb 70 bd 20 05 a8 f8 17 03 03 00 35 6e |zu=.p. .......5n| +000002c0 09 00 fa 13 8f d4 17 40 ee 9e 5f 8a 56 ba 7c 69 |.......@.._.V.|i| +000002d0 05 ee 65 8e fd 9c 62 7f f9 af 04 c7 46 20 07 da |..e...b.....F ..| +000002e0 bc 79 f8 cc 53 c6 fc 47 b5 54 9c fb 4d a3 cf 56 |.y..S..G.T..M..V| +000002f0 a4 57 c5 aa 17 03 03 00 17 d6 ea 39 50 a5 8e 67 |.W.........9P..g| +00000300 b9 79 76 17 77 86 a8 58 fb 86 03 74 1a e4 12 37 |.yv.w..X...t...7| +00000310 17 03 03 00 13 e7 07 59 c3 d0 27 b3 d8 e8 a3 7b |.......Y..'....{| +00000320 df e8 17 08 78 4e 9a 6b |....xN.k| diff --git a/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS b/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS index e557181b295..4892e2b5555 100644 --- a/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS +++ b/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,138 +7,139 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 46 b8 dc eb 72 |....z...v..F...r| -00000010 ac 41 0a 3c 58 14 84 a0 75 91 e1 ca d7 3c c7 2c |.A..| -00000070 42 63 2e 2a a9 13 0c a9 f2 e6 74 14 1e 5c 52 14 |Bc.*......t..\R.| -00000080 03 03 00 01 01 17 03 03 00 17 23 71 3e 39 7a 0c |..........#q>9z.| -00000090 2a fa 89 f1 65 d1 b0 23 96 8e 6a e4 55 2c fd 34 |*...e..#..j.U,.4| -000000a0 ea 17 03 03 00 20 b7 a2 d6 ff b3 b4 db ce f8 90 |..... ..........| -000000b0 f9 a3 9c 0c 8f f0 77 3e 37 f2 d9 e7 84 65 28 f6 |......w>7....e(.| -000000c0 dd fe b9 42 03 3c 17 03 03 02 7a d4 cf 93 f6 2b |...B.<....z....+| -000000d0 64 e3 13 75 41 62 7d bd cf 4f 42 80 23 f4 03 92 |d..uAb}..OB.#...| -000000e0 35 02 5e ed bb c6 2f b1 a8 57 cf d4 69 94 6a db |5.^.../..W..i.j.| -000000f0 39 b8 3a 05 07 dd f1 1d 63 13 22 9b d7 58 68 6f |9.:.....c."..Xho| -00000100 4f ac 79 6a 47 0a 23 35 3c 9b 9f 15 04 e7 6b d8 |O.yjG.#5<.....k.| -00000110 ff df 00 6c 68 5e a0 41 6a a9 34 9f 37 98 c2 3d |...lh^.Aj.4.7..=| -00000120 51 29 73 c4 ad 34 e5 69 78 18 eb 03 55 c0 c6 0d |Q)s..4.ix...U...| -00000130 43 d5 4a 5d cb 53 e6 b9 df e8 8b 0e 98 04 89 bb |C.J].S..........| -00000140 f4 a1 48 01 af d3 42 ef 17 e7 f9 27 b4 b1 63 99 |..H...B....'..c.| -00000150 91 a6 c5 c1 cb 6d 1c 55 b1 69 1c ec b1 b7 c3 cd |.....m.U.i......| -00000160 7a 93 f2 d8 e4 c4 96 43 0a e1 18 b5 9a 3b 57 83 |z......C.....;W.| -00000170 98 ce 74 f2 4c 65 ad 01 aa 76 b5 b0 7c a0 7d 09 |..t.Le...v..|.}.| -00000180 ad d6 20 7d 12 67 f8 4c 2c 41 37 34 66 86 fe 3d |.. }.g.L,A74f..=| -00000190 44 52 f0 08 26 4c b3 e7 71 b3 89 b3 5c 78 7e db |DR..&L..q...\x~.| -000001a0 34 31 dc dc 7c 7d 28 e1 41 96 f4 2f 28 60 9f 5b |41..|}(.A../(`.[| -000001b0 b2 2b 37 6b 3f 3a 37 e2 38 7a 66 40 fe 44 44 72 |.+7k?:7.8zf@.DDr| -000001c0 b4 e3 97 f3 db 73 c8 af 96 c8 a6 24 ef ea 34 8f |.....s.....$..4.| -000001d0 5e 4b 21 22 19 d8 4a db 2e f1 23 90 d0 d2 38 f3 |^K!"..J...#...8.| -000001e0 c6 08 5d 1d c9 a3 f2 6d 01 eb 30 5e cd f4 98 f5 |..]....m..0^....| -000001f0 0d d8 68 4f 00 f4 cd 24 9f c4 3c 6a 31 5d c0 e5 |..hO...$..S8B.| -00000350 6f 99 20 c4 98 59 48 61 e0 13 80 8e 96 25 96 f8 |o. ..YHa.....%..| -00000360 c9 c8 35 9c 35 c0 13 d7 34 24 0b 6e 59 4f 1b 77 |..5.5...4$.nYO.w| -00000370 1f 9a 71 6b 6b dc 71 23 b1 a2 e8 1e c2 a0 b1 8c |..qkk.q#........| -00000380 27 5e 90 c5 f8 65 30 a2 de fc 6b b2 e3 5d 8d 9f |'^...e0...k..]..| -00000390 70 32 3c 92 47 c7 91 10 49 0d f1 3b 41 f1 14 3b |p2<.G...I..;A..;| -000003a0 09 55 f5 78 0e 91 1b 75 a0 58 fc c9 34 82 fe 51 |.U.x...u.X..4..Q| -000003b0 20 73 71 3d 7f 82 a4 29 bc 04 67 d7 30 c7 a5 4b | sq=...)..g.0..K| -000003c0 f3 94 4d 15 35 2a 1e 46 82 3f 36 f4 7b ff 9f 88 |..M.5*.F.?6.{...| -000003d0 3b e6 60 bc 86 51 59 ad 97 58 95 7e 6a 4b c9 6c |;.`..QY..X.~jK.l| -000003e0 34 96 03 17 03 03 00 35 03 94 eb e1 e5 9d eb 8f |4......5........| -000003f0 34 b1 28 3c 9d 26 40 a9 e7 4c 2b bf 37 32 b6 aa |4.(<.&@..L+.72..| -00000400 78 d2 45 0c 6c 5b 0a 0e 8a 3a b6 1a 01 09 3e 0a |x.E.l[...:....>.| -00000410 45 25 c6 83 8a 4a cc 22 d9 29 c8 8a 32 |E%...J.".)..2| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 e0 |..+.....3.$... .| +00000060 70 9a 3d 69 69 1f 8f de d4 c8 7c dc 65 53 9a c6 |p.=ii.....|.eS..| +00000070 77 c2 c4 21 1b 06 2d c4 4f 24 61 52 5b 00 69 14 |w..!..-.O$aR[.i.| +00000080 03 03 00 01 01 17 03 03 00 17 96 99 40 9f d8 9d |............@...| +00000090 70 f0 cf f0 86 3e 7f 4a 3a 8a a4 63 6e e1 7f 24 |p....>.J:..cn..$| +000000a0 f4 17 03 03 00 20 72 bb 5a aa 0e 2e d9 cc 38 0c |..... r.Z.....8.| +000000b0 c8 b9 88 08 6f 19 d8 38 14 14 d7 97 42 6c 45 43 |....o..8....BlEC| +000000c0 51 dc 2b f6 02 e2 17 03 03 02 7a 8d 04 2f 64 c0 |Q.+.......z../d.| +000000d0 e2 7b b5 20 9d 04 69 5e 88 82 aa f3 c6 b2 8d 6c |.{. ..i^.......l| +000000e0 41 08 c3 b1 0c 7d d1 5f d6 e6 b7 1d c0 ad 2b 0d |A....}._......+.| +000000f0 02 c5 f7 6d a0 87 91 07 20 d3 d4 2e 5a 7d 5e 29 |...m.... ...Z}^)| +00000100 37 2b ac 5f d6 cb eb e9 99 a7 05 f7 e7 ea 9c 99 |7+._............| +00000110 cd 33 25 f8 45 95 43 f4 7a 59 2a 91 8c e2 ac 84 |.3%.E.C.zY*.....| +00000120 ba 99 ef d0 d7 ea 9b db 31 b0 27 0c 81 3b b2 83 |........1.'..;..| +00000130 20 c4 8b 7e 05 ac c6 82 e9 56 5a a2 b6 7c c7 33 | ..~.....VZ..|.3| +00000140 a8 31 2f ad 60 be ec c3 2d c0 a8 b4 40 50 98 ea |.1/.`...-...@P..| +00000150 83 d1 cc a8 34 20 11 7c 2e f7 7c ca d8 27 03 a2 |....4 .|..|..'..| +00000160 58 86 e8 e6 41 46 07 18 c7 a7 61 f9 cc 2f 7d 1e |X...AF....a../}.| +00000170 bb 34 7c 6e cb b3 9c 03 2f b0 dd e9 a1 32 13 10 |.4|n..../....2..| +00000180 85 1d fa a6 bf c7 4d ec 94 8f 26 07 94 34 b3 5f |......M...&..4._| +00000190 b8 e4 da 6f 3d 5b 0a 61 8f 44 58 10 1a 4c f3 bc |...o=[.a.DX..L..| +000001a0 ff c7 8f 09 0a e4 1b 35 e8 a9 dc 9c 14 86 e5 67 |.......5.......g| +000001b0 7e 96 e9 79 8d b2 d7 34 a0 7f 43 07 11 f1 03 68 |~..y...4..C....h| +000001c0 95 5e f5 fa e7 8f c8 d6 5b 23 c4 84 e4 c5 40 58 |.^......[#....@X| +000001d0 80 4a ac b7 a7 07 21 93 c1 a9 ad 9a 89 f7 f3 9e |.J....!.........| +000001e0 bb 7d 2a 00 d0 e0 66 9d f7 86 4a ba b1 c9 1e 3b |.}*...f...J....;| +000001f0 f1 c6 6e c1 9c 09 85 38 9d fa 5a b9 ca bb a4 f5 |..n....8..Z.....| +00000200 9e 3f ba d4 31 7d aa d7 f9 bf 83 05 5c 1f 61 18 |.?..1}......\.a.| +00000210 d4 5e 16 98 c6 92 7b bd 12 96 18 c7 33 75 ad 08 |.^....{.....3u..| +00000220 d1 0b 47 4c c8 73 3e 68 fb 53 ff e0 1a 10 6c 5a |..GL.s>h.S....lZ| +00000230 7f 9d 92 32 2f c2 2d 95 7d c6 ef 18 9b 44 a1 bc |...2/.-.}....D..| +00000240 6a f5 88 79 e1 00 a3 14 8f 66 07 03 16 2a 53 80 |j..y.....f...*S.| +00000250 9b 26 80 0d 0b 5e 0c c6 c9 fa a1 3b c9 a6 91 1f |.&...^.....;....| +00000260 bd fb 79 24 ab 93 e4 25 d1 a6 41 8b 9e a9 06 0f |..y$...%..A.....| +00000270 80 2e 4e 8c 20 2c 1e a8 7e 63 7a 4f b8 90 c3 56 |..N. ,..~czO...V| +00000280 a3 9e 63 2a 8b 85 9e ef 66 f5 16 be 79 c3 9b 47 |..c*....f...y..G| +00000290 dc 1c 75 0b 30 3c db 32 e8 ec 33 f9 9f 26 3d 56 |..u.0<.2..3..&=V| +000002a0 36 e9 ea 83 57 c4 59 ac 73 db 04 5a 1d 38 9b e4 |6...W.Y.s..Z.8..| +000002b0 47 50 f8 92 92 7f c9 09 4f f4 9c ab 3e 03 df 80 |GP......O...>...| +000002c0 cc 5b 50 0b 06 ef 8c 59 d2 f6 f3 a4 16 e7 0f 90 |.[P....Y........| +000002d0 c8 79 95 0a 39 0f 33 69 31 29 1c 30 77 72 58 b5 |.y..9.3i1).0wrX.| +000002e0 cf 0e 4c 30 fc 0a 01 93 b1 20 21 34 2a ce 28 8d |..L0..... !4*.(.| +000002f0 57 71 3e c9 b1 51 c9 4f e5 e4 09 0b 1e 32 52 4e |Wq>..Q.O.....2RN| +00000300 d0 be f2 a2 90 75 f4 a8 61 66 43 84 74 4e bb 28 |.....u..afC.tN.(| +00000310 7b ea 68 96 92 6d 4b 8c af 50 13 84 92 b9 6b 48 |{.h..mK..P....kH| +00000320 60 1c 60 62 28 a2 37 d1 1c 86 d4 60 27 a6 5b 6d |`.`b(.7....`'.[m| +00000330 88 d7 56 21 b7 86 f5 b6 34 f9 55 cf 47 f8 4f 90 |..V!....4.U.G.O.| +00000340 78 5c 56 52 97 17 03 03 00 99 35 71 51 6f 73 ba |x\VR......5qQos.| +00000350 76 60 e1 4a 5f ec ce 52 b6 91 58 3d 0c ea e6 58 |v`.J_..R..X=...X| +00000360 7e ee da 1e aa df bb 8e c9 89 ce 43 bd e7 34 9b |~..........C..4.| +00000370 b8 4b dd 50 73 0c f7 e5 15 e0 a1 c3 bd 07 08 62 |.K.Ps..........b| +00000380 a2 d5 2e 9f 46 f7 4d 9c ae ad be 22 89 0f b0 3e |....F.M...."...>| +00000390 82 1c 80 60 38 39 4f 06 f9 fc 4c f8 02 bf b3 5a |...`89O...L....Z| +000003a0 25 22 f4 62 61 ba eb 78 b2 40 68 ea 99 ef 95 90 |%".ba..x.@h.....| +000003b0 b1 b5 25 17 81 43 5c 15 bd a9 1f e8 0f b9 91 be |..%..C\.........| +000003c0 f1 47 91 99 ec 50 3b fa c2 06 fc 89 09 a3 d7 b3 |.G...P;.........| +000003d0 ed e3 3d 41 57 07 4b b0 3d 02 51 7e 13 bb d3 68 |..=AW.K.=.Q~...h| +000003e0 49 4c 6a 17 03 03 00 35 63 f7 b5 68 31 22 c7 f5 |ILj....5c..h1"..| +000003f0 50 ae c0 81 0f 50 fb ba 50 72 8a d7 e0 c0 73 07 |P....P..Pr....s.| +00000400 d0 88 ed 6d 7b e7 66 b3 8d e3 10 ca 2f 68 c3 39 |...m{.f...../h.9| +00000410 d9 b9 09 44 78 4a 11 91 fb 51 ea 9f 9a |...DxJ...Q...| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 7a 3e 62 91 75 b4 |..........z>b.u.| -00000010 58 7d 61 ac 42 4b 1b 91 86 cd 3f c0 6d 30 5a 01 |X}a.BK....?.m0Z.| -00000020 11 1e 77 87 92 50 bb a0 d2 c6 84 b6 10 37 02 ab |..w..P.......7..| -00000030 2d c2 c2 12 0a db f5 8f e4 1f dd 16 ec 83 ad db |-...............| -00000040 2d 8b ec fa aa 56 44 4e d4 af ce d2 9f 44 3d de |-....VDN.....D=.| -00000050 12 29 db bc 29 2a df 99 d7 d0 53 79 84 a4 b8 2d |.)..)*....Sy...-| -00000060 8b 5c e6 a4 b7 98 07 5a f4 63 10 21 87 13 09 07 |.\.....Z.c.!....| -00000070 28 98 49 48 07 70 c1 ab 8b 62 6d 40 a8 47 27 67 |(.IH.p...bm@.G'g| -00000080 d6 ad 29 8d 2e 14 34 14 18 6b dd f0 76 3b 91 f9 |..)...4..k..v;..| -00000090 e1 93 a2 1c 3a 5e 18 a3 c9 ca b0 c9 cf d9 3c f5 |....:^........<.| -000000a0 a3 38 c7 83 53 67 14 ba 65 6f 11 a2 ef 78 7e ea |.8..Sg..eo...x~.| -000000b0 4a 90 c9 aa bf e9 8e ff 8c 9d 7c 5f 56 c3 9b 16 |J.........|_V...| -000000c0 c1 8a a9 51 24 20 86 dc 99 ac d2 28 af 7b 2d 6e |...Q$ .....(.{-n| -000000d0 16 9b 71 71 82 00 94 51 a4 4f 22 c1 26 a2 6f 67 |..qq...Q.O".&.og| -000000e0 d9 45 ff 80 13 39 16 0f 9c 43 76 54 e5 12 0f 89 |.E...9...CvT....| -000000f0 95 ed 75 df eb cb 6b d2 77 fd fa 37 d7 a3 31 b5 |..u...k.w..7..1.| -00000100 61 47 69 8f 99 55 70 d0 96 b0 f7 a9 1b 53 69 a3 |aGi..Up......Si.| -00000110 e4 59 cc a1 d9 4b d5 4f e2 47 c1 53 30 60 50 03 |.Y...K.O.G.S0`P.| -00000120 c7 07 67 3f 68 ce 8c 32 7e f1 93 12 ba d8 67 21 |..g?h..2~.....g!| -00000130 71 4f c9 ca ae 7b 56 8d f7 64 14 e3 8d d6 a6 ed |qO...{V..d......| -00000140 d0 63 5e 00 1e f7 8a 0c 1e c3 24 e0 bd e2 e8 99 |.c^.......$.....| -00000150 da ca 01 9e fb 21 9e 1f 57 98 f1 36 7d c8 a8 7b |.....!..W..6}..{| -00000160 4b 27 13 fb 8c ab d6 b3 27 3e f5 b5 08 eb cb a9 |K'......'>......| -00000170 b0 a4 d4 3e c9 14 08 75 51 83 48 03 e7 79 65 30 |...>...uQ.H..ye0| -00000180 a4 1a 4f a8 7a 41 c8 af 9e 74 89 4d ec eb 58 9b |..O.zA...t.M..X.| -00000190 20 db 80 ce e0 c8 a7 1c b2 62 fc 85 7d 87 ca 00 | ........b..}...| -000001a0 64 4c 25 4d 3c b2 bf 9d 46 c5 04 b5 dd 7a 29 87 |dL%M<...F....z).| -000001b0 29 30 2e bc 42 31 9b f2 eb 7b 58 63 91 28 6f 43 |)0..B1...{Xc.(oC| -000001c0 6b c1 4e 00 b2 4b 9d 0c ef 18 5b 61 ec 77 84 e1 |k.N..K....[a.w..| -000001d0 88 49 f9 e2 71 2e 35 23 b8 73 6d c2 52 d1 2f ad |.I..q.5#.sm.R./.| -000001e0 55 40 4e a2 b0 14 1b 50 d7 9d 12 80 89 ab 88 a5 |U@N....P........| -000001f0 01 16 88 d5 4f 95 0c ce 79 c7 49 27 4b 44 4d fe |....O...y.I'KDM.| -00000200 f5 cd 95 08 b9 26 8d 52 ff d7 bc 47 11 16 d5 d0 |.....&.R...G....| -00000210 7d 4c 3c 04 74 92 5b 85 d2 2c 95 b8 4b 02 0b 66 |}L<.t.[..,..K..f| -00000220 60 7d b9 12 6e d3 06 73 cc c2 69 b9 fe ad f9 4c |`}..n..s..i....L| -00000230 f6 24 a0 eb 96 f0 b8 7c 32 dc 4c 67 04 83 15 84 |.$.....|2.Lg....| -00000240 f9 ef 70 e7 55 85 0e 8f b3 78 20 2c ed 69 29 89 |..p.U....x ,.i).| -00000250 d4 d8 5e 97 16 59 90 0f 79 41 6e cf 02 d3 9d 08 |..^..Y..yAn.....| -00000260 e4 0c 27 0c 74 97 c6 d6 89 6b c9 65 37 7b ae 6b |..'.t....k.e7{.k| -00000270 b7 0f e8 70 57 a3 1c 95 8d 66 da 4e 34 51 c8 e0 |...pW....f.N4Q..| -00000280 0e 83 e3 24 64 17 03 03 00 99 e3 31 2c ae ae 1c |...$d......1,...| -00000290 64 6c fc 36 c8 9f c2 88 16 c7 b2 ae 4a ef 3a 90 |dl.6........J.:.| -000002a0 f4 ad f2 91 58 37 7c 94 c2 e3 ed 76 c5 90 fb e6 |....X7|....v....| -000002b0 88 08 a6 a2 53 5a 78 cb bd f2 3c 6e 36 b4 cd 87 |....SZx...XCK.......N..ZR..| +000000c0 bd fa f0 a7 88 d5 9e 76 9b 2b 23 fb 37 c0 f1 0a |.......v.+#.7...| +000000d0 d2 df d4 2c 5d 8c 64 f0 98 3c 85 3f bb ed 30 44 |...,].d..<.?..0D| +000000e0 eb cb fc 47 e5 8a 57 ff 37 23 6d e2 75 a7 15 e4 |...G..W.7#m.u...| +000000f0 dc f9 02 8f c4 af d8 e8 bb 07 43 90 5b c2 86 f3 |..........C.[...| +00000100 40 22 a7 bb b6 f1 f6 4c 2e d6 fd d8 02 f0 3d 27 |@".....L......='| +00000110 89 38 97 7d 6e d3 6c b1 4c 87 ca 30 e9 ec fe b3 |.8.}n.l.L..0....| +00000120 db 62 ea 2f 3a 83 95 18 4e 44 4f 97 c4 ff f6 bb |.b./:...NDO.....| +00000130 0b b0 98 c7 c6 c7 94 0a 8b c9 c0 d9 51 d3 6a e1 |............Q.j.| +00000140 36 55 79 c4 37 75 6f e7 14 53 60 9e 22 00 fe d7 |6Uy.7uo..S`."...| +00000150 ef e4 ca 60 38 12 25 8c c6 c9 7e 5f 1a 7c f1 c1 |...`8.%...~_.|..| +00000160 a7 15 b2 f4 32 31 de c8 a2 d4 59 46 1e 68 a6 94 |....21....YF.h..| +00000170 b8 18 52 df 44 01 0b a0 a0 02 60 83 84 fc ad 99 |..R.D.....`.....| +00000180 fc 60 0b 23 0a 7a f9 73 bf d8 a5 af 9b ea dd a3 |.`.#.z.s........| +00000190 fb 5b 41 17 95 0a 57 4a 94 7e 24 9f 31 74 06 65 |.[A...WJ.~$.1t.e| +000001a0 95 90 40 20 17 0b 95 22 b8 49 4e a6 a4 be e1 74 |..@ ...".IN....t| +000001b0 01 a2 7e cd 60 50 46 5c fd 2a 88 90 ef 7f 6c b8 |..~.`PF\.*....l.| +000001c0 3e a1 40 8e 91 cd 8d db ad 81 d0 08 b0 d0 d7 ae |>.@.............| +000001d0 18 4f 47 9b 1a 66 8b a5 d2 fb 01 d3 67 79 46 71 |.OG..f......gyFq| +000001e0 5a 49 dd df 06 c6 57 c7 e0 b1 60 39 d4 a9 37 88 |ZI....W...`9..7.| +000001f0 31 0d c0 92 4e c7 2a 25 c4 df b0 d8 df bb 31 1b |1...N.*%......1.| +00000200 ff 0a 34 46 46 88 0b 11 7d 20 32 cd 01 d0 3f 11 |..4FF...} 2...?.| +00000210 e1 6e 63 42 d7 4a 83 ab ad f7 51 bd c3 37 2b 76 |.ncB.J....Q..7+v| +00000220 9e bb 45 3b 81 d8 47 71 02 b9 fe 7c 56 46 78 3e |..E;..Gq...|VFx>| +00000230 9e 94 00 1b 98 17 72 37 c0 e5 36 a9 f0 02 b7 cf |......r7..6.....| +00000240 f0 b4 66 10 1b 91 07 5f bb 22 e8 12 d9 e3 33 dd |..f...._."....3.| +00000250 87 66 e4 f6 00 f6 3a dc 19 59 af ce 8e ae c4 d3 |.f....:..Y......| +00000260 03 d8 25 02 40 7e 95 70 31 85 53 bc 9e 96 11 69 |..%.@~.p1.S....i| +00000270 5b 2f b9 17 48 f4 ae c5 a1 c5 d1 7f 4a 10 06 b6 |[/..H.......J...| +00000280 2e 34 6c 09 12 17 03 03 00 99 16 4c 04 64 97 e0 |.4l........L.d..| +00000290 26 e1 66 e9 34 05 d7 d3 75 e3 b9 de 56 15 51 67 |&.f.4...u...V.Qg| +000002a0 fb fe 9a c6 9a 3c 38 08 2c c8 8c dd fe 49 c5 ed |.....<8.,....I..| +000002b0 a8 54 86 90 2c f6 7c d1 12 02 99 94 5e 2e 4b 4e |.T..,.|.....^.KN| +000002c0 84 e9 b4 96 5c dc 56 28 3d ea a9 4f 8f ad 51 ff |....\.V(=..O..Q.| +000002d0 02 b1 b9 7a 29 e5 32 7c 2a 8b 60 5d e2 fc b4 8f |...z).2|*.`]....| +000002e0 06 32 4a ea 37 ed 03 f0 68 72 b7 83 1f 04 10 2b |.2J.7...hr.....+| +000002f0 24 db 5b 10 6c 41 55 40 54 69 07 39 d4 db ac 10 |$.[.lAU@Ti.9....| +00000300 77 9f 04 f4 b9 3f 35 7e 04 af ab 7a a0 47 b9 d9 |w....?5~...z.G..| +00000310 4c 6e 25 00 ce ef 93 3f 28 2c 2d f6 42 e4 5f 3e |Ln%....?(,-.B._>| +00000320 26 92 13 17 03 03 00 35 fb 14 eb 5f 18 61 75 ba |&......5..._.au.| +00000330 e4 dc d2 95 fe 93 bb 54 29 e3 38 e3 59 54 81 9f |.......T).8.YT..| +00000340 4e 29 be c6 e6 cd ad 8c 9d 6a ad 28 ec d3 a6 e4 |N).......j.(....| +00000350 bc 5e 8c df a8 7e 14 d8 69 3c 30 7c 0a 17 03 03 |.^...~..i<0|....| +00000360 00 17 10 73 c0 75 88 af 51 90 ff 3f b2 83 47 27 |...s.u..Q..?..G'| +00000370 19 c0 e6 cd 14 a4 c7 8d a0 17 03 03 00 13 fb 1f |................| +00000380 ed 8e 47 c8 79 f9 53 df 6d 97 a7 1d 53 8d 80 85 |..G.y.S.m...S...| +00000390 dd |.| diff --git a/crypto/tls/testdata/Client-TLSv13-ECDSA b/crypto/tls/testdata/Client-TLSv13-ECDSA index b6a3b2addbe..eeab8711723 100644 --- a/crypto/tls/testdata/Client-TLSv13-ECDSA +++ b/crypto/tls/testdata/Client-TLSv13-ECDSA @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,81 +7,82 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 24 80 76 3d db |....z...v..$.v=.| -00000010 cf 32 53 04 de ce 2e 74 95 bb 30 a8 d5 5e ab ed |.2S....t..0..^..| -00000020 3c 1e 1a ae 92 63 8f 40 0b ce a4 20 00 00 00 00 |<....c.@... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 a5 7b 07 50 bc |....z...v...{.P.| +00000010 01 11 74 76 99 fb 85 e5 40 6b 02 14 d9 64 b1 8a |..tv....@k...d..| +00000020 8b 78 a3 ee 2e 4d b0 96 14 3a fb 20 00 00 00 00 |.x...M...:. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 d2 |..+.....3.$... .| -00000060 b3 86 f1 35 22 26 89 f4 07 ab b8 f5 27 a6 d5 c9 |...5"&......'...| -00000070 87 00 59 43 b8 df da 92 f6 f5 ed f4 8d 04 26 14 |..YC..........&.| -00000080 03 03 00 01 01 17 03 03 00 17 ed 6b 14 3a 82 c5 |...........k.:..| -00000090 88 9d a4 96 c7 c4 c7 73 63 c6 58 65 d0 d4 a6 cb |.......sc.Xe....| -000000a0 dc 17 03 03 02 22 e8 c5 15 54 3c 26 7b 87 8c d3 |....."...T<&{...| -000000b0 99 b0 af 98 21 1b 8f be f5 d8 40 c9 05 97 39 fd |....!.....@...9.| -000000c0 3d b2 da 2d 80 26 c9 24 cd 14 0b 48 2e d7 c4 dc |=..-.&.$...H....| -000000d0 4c 61 1e 5d 46 ce 66 cd 94 50 a4 e8 c4 d7 f0 48 |La.]F.f..P.....H| -000000e0 20 16 52 fb 12 04 17 48 7d 65 49 50 c5 b8 e6 9c | .R....H}eIP....| -000000f0 be f6 58 09 ea 8b 94 51 93 cf 0d 7a 76 88 78 cb |..X....Q...zv.x.| -00000100 37 83 43 fa 37 d5 5b 3f 10 1d 07 b1 bb 9b ac 3a |7.C.7.[?.......:| -00000110 43 e0 62 b1 fe 64 43 83 53 49 96 9e 81 1c 05 64 |C.b..dC.SI.....d| -00000120 40 2a 1b 98 5f ed 8d 47 52 2c db 84 8b 6a 1e 3b |@*.._..GR,...j.;| -00000130 de bb 7d 20 e6 cf 2a 79 2e c4 54 71 56 2f 79 45 |..} ..*y..TqV/yE| -00000140 07 3f 05 6c 82 e8 ab f7 62 0a 28 e0 db 83 6b bd |.?.l....b.(...k.| -00000150 55 81 8f 3f b6 1f d0 83 cd 97 67 71 56 f5 13 aa |U..?......gqV...| -00000160 45 95 65 ce 1e 42 bf 6a 83 6e bc 2e 41 28 79 b7 |E.e..B.j.n..A(y.| -00000170 b8 3f 6e 64 14 8d ed 3a a4 02 06 46 17 e5 c7 f8 |.?nd...:...F....| -00000180 72 f1 5f 9b 14 96 c9 c6 53 e6 32 b2 0b cc d5 d7 |r._.....S.2.....| -00000190 89 1e d9 52 fb 8f 48 8b 41 6e c6 f3 55 57 41 5d |...R..H.An..UWA]| -000001a0 95 03 9c 34 ea 3c a8 58 8d b7 89 82 e1 40 e0 60 |...4.<.X.....@.`| -000001b0 22 ab 23 30 e8 f0 4e 21 a1 11 0a 7f 18 80 ad de |".#0..N!........| -000001c0 41 ba a1 12 60 31 60 0f 84 f6 91 b1 ae ca f5 81 |A...`1`.........| -000001d0 3e d6 4e 3a 89 b6 b0 fe 3f 27 18 20 65 a9 d4 6c |>.N:....?'. e..l| -000001e0 ac 8a 46 08 e2 7d 06 6d 52 8c 69 9e 24 9b 8d f9 |..F..}.mR.i.$...| -000001f0 b7 a7 74 87 bd f9 84 ca 18 7d 5b 50 1d 8e 64 e1 |..t......}[P..d.| -00000200 39 6f f7 56 5a ef 08 6b e2 a1 87 e4 7a 5e ea b6 |9o.VZ..k....z^..| -00000210 12 75 2d ee e9 af a4 36 99 91 88 11 97 f3 d5 fb |.u-....6........| -00000220 8b 52 59 bc 9c 18 03 5b b1 59 47 ae d4 bb a1 65 |.RY....[.YG....e| -00000230 cf bf 40 54 e5 e7 6e e0 0c 26 0e a1 d2 4d 41 19 |..@T..n..&...MA.| -00000240 36 b5 b6 48 33 96 8a e3 a5 56 9b 34 16 ae 36 48 |6..H3....V.4..6H| -00000250 c5 ff 12 a7 33 f4 76 40 de d1 4b 41 ed 18 3b 04 |....3.v@..KA..;.| -00000260 06 32 6e f3 57 c6 be 72 58 7f 78 b7 91 65 00 a8 |.2n.W..rX.x..e..| -00000270 8d 5c 7f ff 0a 62 d4 99 82 b2 6b c8 80 3e 89 30 |.\...b....k..>.0| -00000280 dd 31 60 7a 00 6e a2 13 c7 58 08 b0 d5 32 03 2e |.1`z.n...X...2..| -00000290 08 86 a2 97 7a f0 a1 95 10 5f a2 d6 fc e7 a3 93 |....z...._......| -000002a0 16 a2 3d 33 04 e7 aa 3b 99 a5 ce c7 2c 28 71 bb |..=3...;....,(q.| -000002b0 ed e6 b9 5a a5 ec d1 44 54 e0 ff 41 cf 1a cb ff |...Z...DT..A....| -000002c0 67 43 6b af 87 19 40 74 17 03 03 00 a4 bc ef 32 |gCk...@t.......2| -000002d0 22 da e9 d5 93 ce 06 bd 3d 6c 2e f0 0c de ec b8 |".......=l......| -000002e0 12 d6 28 17 c6 64 aa 8d 4b 04 76 9e 41 3c 4a 94 |..(..d..K.v.Aru@.0.| -000003a0 fd 46 9d 5e 79 39 e1 a8 f9 27 2b |.F.^y9...'+| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 67 |..+.....3.$... g| +00000060 b0 dc 13 4f 2b 92 43 27 38 b5 2c 7a 3a 87 83 6f |...O+.C'8.,z:..o| +00000070 a1 cc 43 fa 90 9e 2e 4d 88 f6 60 d4 20 32 6a 14 |..C....M..`. 2j.| +00000080 03 03 00 01 01 17 03 03 00 17 9b 51 d0 81 30 4b |...........Q..0K| +00000090 52 65 8b b5 fe 1a cc 44 c9 7a 10 83 41 0b 1a 00 |Re.....D.z..A...| +000000a0 76 17 03 03 02 22 4e 55 d0 64 9c 41 c8 22 2c 9c |v...."NU.d.A.",.| +000000b0 0e 0a 0c 2b 2b 2e 6e 08 d5 54 75 61 99 bf ea f5 |...++.n..Tua....| +000000c0 ca 12 3e 44 7f 81 a8 40 d1 7c 4d a0 a3 d2 f3 07 |..>D...@.|M.....| +000000d0 40 af 68 81 69 dd 7c 77 24 26 87 73 73 5e d2 0c |@.h.i.|w$&.ss^..| +000000e0 2a 32 c5 34 50 ef a8 0f 63 12 3a 47 34 8f f2 c6 |*2.4P...c.:G4...| +000000f0 9f bd 81 bf ea 69 47 04 8b 87 64 4e 67 81 10 a5 |.....iG...dNg...| +00000100 f1 76 92 5e d6 11 a5 48 5b cc ef a8 43 dd cf f5 |.v.^...H[...C...| +00000110 20 9d b8 2f f4 0d 92 10 55 af d1 fa ab 64 5f 99 | ../....U....d_.| +00000120 3e 6b e9 70 70 f1 22 d9 05 04 89 3a fa 65 ae 91 |>k.pp."....:.e..| +00000130 9d 07 ea 54 93 2d 02 0c c0 70 d9 e9 f0 9a 5a 81 |...T.-...p....Z.| +00000140 c6 c6 79 e0 e1 90 ad 34 78 bf d3 c8 9c 68 2e ac |..y....4x....h..| +00000150 e6 2d c0 e5 c8 3c 77 80 d7 dd e5 a4 ac b8 36 4f |.-...@..I<..FW.Ye.| +00000170 4e db 21 ea ab 72 47 79 e6 c1 4f ea 17 e3 b4 73 |N.!..rGy..O....s| +00000180 9d e2 e5 72 be 88 0a 60 1e 35 02 67 33 a0 7a 05 |...r...`.5.g3.z.| +00000190 b8 ae 05 b2 53 6c cd c5 e3 a5 16 56 2b b0 0e 8e |....Sl.....V+...| +000001a0 a0 ca 54 c0 34 6b 00 22 69 de e1 57 81 48 c6 1a |..T.4k."i..W.H..| +000001b0 cc 88 f6 15 1c 7e b6 1f b0 48 82 75 6b ff 42 78 |.....~...H.uk.Bx| +000001c0 f9 85 10 86 5b af 31 62 f6 7b d4 8a a6 86 3f 99 |....[.1b.{....?.| +000001d0 9b ce 91 c0 4d 44 5b 3f 16 81 d0 a9 4a e0 2d 85 |....MD[?....J.-.| +000001e0 a4 80 91 64 13 20 33 dc 84 48 da 79 2e 73 cb 78 |...d. 3..H.y.s.x| +000001f0 9c 05 8a 6c 42 ce b0 b0 45 3c 05 47 47 f7 92 3b |...lB...E<.GG..;| +00000200 d2 fb 65 f0 40 a3 52 b7 aa 04 ae 71 84 35 12 7a |..e.@.R....q.5.z| +00000210 33 f8 8b 0d 21 a3 29 ad 78 de df 7f 53 71 fb 5f |3...!.).x...Sq._| +00000220 a5 ab 07 89 3a 1f e9 ca 6d 8d bb 04 39 8d b3 50 |....:...m...9..P| +00000230 7e 2e bd 0f b8 ff 4f 3f d1 a5 23 b9 80 33 da b0 |~.....O?..#..3..| +00000240 2c dc 0f c2 26 b2 cf 59 d9 10 ef 66 52 40 e4 54 |,...&..Y...fR@.T| +00000250 28 5e 7f c1 94 62 8f 4f 9b 94 fc c9 32 af f5 17 |(^...b.O....2...| +00000260 5d 04 32 08 83 f4 90 68 68 01 d3 00 ed 82 f3 da |].2....hh.......| +00000270 81 2e d5 df 1e 13 c3 c3 76 83 c4 67 23 c4 32 c0 |........v..g#.2.| +00000280 59 5d dd 56 78 d9 74 ef 7b d5 c9 13 4d 62 29 85 |Y].Vx.t.{...Mb).| +00000290 ca 24 53 1a b1 2b 09 a1 a6 26 db 13 cf 2a 2b 92 |.$S..+...&...*+.| +000002a0 85 a3 51 2b 24 e1 90 2a fe 0c 74 ee 86 cc 3b 6a |..Q+$..*..t...;j| +000002b0 07 21 a6 b6 97 a4 e0 9f 3d 75 9a 2b 9e 91 ef d8 |.!......=u.+....| +000002c0 c9 94 28 ba 40 e4 cc 6a 17 03 03 00 a4 ab c3 c1 |..(.@..j........| +000002d0 32 1d 44 0d f7 85 e3 85 df 9e bb 0c 82 18 a2 9f |2.D.............| +000002e0 27 de 78 4f 06 9b 43 59 27 b5 8e 34 4d 96 b3 96 |'.xO..CY'..4M...| +000002f0 af 8b 98 d0 36 91 52 df 9c aa c2 fe e7 0f ed ca |....6.R.........| +00000300 ef 57 73 97 cc c8 dc 7c c8 15 73 ad a6 3e 54 93 |.Ws....|..s..>T.| +00000310 1a ab 72 f6 e0 e3 cb bb fe a5 d1 45 47 f3 1a 89 |..r........EG...| +00000320 40 f7 9d f5 e4 61 16 fa 12 0a 62 24 a7 34 ab 6f |@....a....b$.4.o| +00000330 08 85 b2 fe b2 5c 49 59 7b cb 05 b2 e3 1a 37 79 |.....\IY{.....7y| +00000340 b1 27 28 a5 ab ee ae 72 11 19 61 c0 3b ed 32 ec |.'(....r..a.;.2.| +00000350 57 26 76 8e 42 3c 98 4a ec 10 4e e0 eb e2 19 3d |W&v.B<.J..N....=| +00000360 67 47 99 9c e5 97 a4 07 ff 7a b5 15 65 0e b9 e4 |gG.......z..e...| +00000370 e3 17 03 03 00 35 61 d9 d8 36 a0 1e 83 b0 f8 1f |.....5a..6......| +00000380 74 61 a0 4b 93 7f 98 8b 63 1c 63 82 f4 cd 57 8d |ta.K....c.c...W.| +00000390 1f 75 7a 6d a9 1d e2 35 0b 2b 9a 5f 5f 71 cd 46 |.uzm...5.+.__q.F| +000003a0 48 7f 27 af a5 da 8b 35 b1 18 39 |H.'....5..9| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 09 35 dd b0 97 |..........5.5...| -00000010 7b a4 5b ef 16 90 e4 15 aa 19 e4 5b e8 f1 11 c0 |{.[........[....| -00000020 e0 fa 4b 0e df a3 4a 7c cd 9a 0a c4 05 65 e9 5b |..K...J|.....e.[| -00000030 8b 0b e0 3c b2 5a cc eb 87 2b 67 0d 9f 19 d0 ec |...<.Z...+g.....| -00000040 17 03 03 00 17 68 1f ad 70 7c 49 62 6b 2f 67 15 |.....h..p|Ibk/g.| -00000050 d1 bf bb 35 b3 b3 2b f3 12 27 b6 0e 17 03 03 00 |...5..+..'......| -00000060 13 23 39 42 9f 8a 9e 68 41 39 fa 3b 50 bc 56 59 |.#9B...hA9.;P.VY| -00000070 d0 3a 5a 9a |.:Z.| +00000000 14 03 03 00 01 01 17 03 03 00 35 3d 13 d4 8c 88 |..........5=....| +00000010 73 62 97 8b 18 04 f7 05 8d c8 56 d2 f4 0a 86 93 |sb........V.....| +00000020 d4 6f 08 1c d8 7f 57 be 50 03 a7 4a c8 37 80 04 |.o....W.P..J.7..| +00000030 43 1b 2a 86 21 25 ae 84 53 80 0c f6 4f 2e 73 67 |C.*.!%..S...O.sg| +00000040 17 03 03 00 17 43 99 86 f2 2f a2 22 05 36 d8 47 |.....C.../.".6.G| +00000050 c5 57 92 93 c7 79 d9 fd 13 70 8f 75 17 03 03 00 |.W...y...p.u....| +00000060 13 15 90 47 ea af 57 89 d4 19 70 e7 e1 ce 68 8a |...G..W...p...h.| +00000070 7b 83 8c a5 |{...| diff --git a/crypto/tls/testdata/Client-TLSv13-Ed25519 b/crypto/tls/testdata/Client-TLSv13-Ed25519 index 3a2915d613e..274620a2576 100644 --- a/crypto/tls/testdata/Client-TLSv13-Ed25519 +++ b/crypto/tls/testdata/Client-TLSv13-Ed25519 @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,63 +7,64 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 b2 4d aa 76 5b |....z...v...M.v[| -00000010 b7 38 95 18 e6 81 66 f8 27 82 26 2c b3 44 50 b0 |.8....f.'.&,.DP.| -00000020 f4 a8 f5 f2 87 f0 9d 85 4f ac 60 20 00 00 00 00 |........O.` ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 5a e2 b6 f0 cf |....z...v..Z....| +00000010 f2 85 49 e0 28 8c d7 89 41 39 5f a4 e8 41 9b f6 |..I.(...A9_..A..| +00000020 1d 2b 3a 8a 3e a3 40 29 76 17 22 20 00 00 00 00 |.+:.>.@)v." ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 e7 |..+.....3.$... .| -00000060 c2 3e 68 73 d9 fd 6e 69 16 15 85 84 24 45 36 47 |.>hs..ni....$E6G| -00000070 1b ad d9 c4 dc 4a 61 c6 12 5c 22 bf 1e 2f 59 14 |.....Ja..\"../Y.| -00000080 03 03 00 01 01 17 03 03 00 17 0f a4 05 81 10 48 |...............H| -00000090 c7 b7 78 9b 56 14 6c 9f 55 28 e3 4c 42 80 cc 1c |..x.V.l.U(.LB...| -000000a0 31 17 03 03 01 50 0d af 3b 08 02 84 89 42 b5 75 |1....P..;....B.u| -000000b0 c5 8f 9f c2 b1 dc cb 7c 6a d5 31 41 9a 16 8f fa |.......|j.1A....| -000000c0 74 40 21 5d f9 cc b0 1d 30 80 87 9a b2 57 58 53 |t@!]....0....WXS| -000000d0 2c 9e 5c 97 20 9c 81 77 16 25 62 9b fc a4 e1 9a |,.\. ..w.%b.....| -000000e0 80 c8 9a 4c f6 fc ae 79 a5 c2 26 4b 55 41 ff d0 |...L...y..&KUA..| -000000f0 25 4b 70 c9 ad b6 04 80 65 19 e0 fe 05 e7 b4 dc |%Kp.....e.......| -00000100 53 8f f8 3b ed 2c df b9 08 c2 da 60 b9 23 17 50 |S..;.,.....`.#.P| -00000110 da 0f 24 76 15 21 e6 e9 a8 f5 3e 08 cc 1b ee 92 |..$v.!....>.....| -00000120 2b 01 92 8d f9 4f 5a 3a 53 11 fc 32 52 cc af cd |+....OZ:S..2R...| -00000130 7b 94 0e 76 10 c2 16 36 2d a4 64 69 1c 05 70 20 |{..v...6-.di..p | -00000140 0d 23 cd 4a 33 c5 c7 db db 0f f8 b6 42 0c 83 0a |.#.J3.......B...| -00000150 a1 73 68 fb 87 2c 9d d2 d3 cf d7 3a bb 36 7e 83 |.sh..,.....:.6~.| -00000160 c3 3f bc e2 61 d9 c2 8b 15 a2 cc bf 14 a0 69 f4 |.?..a.........i.| -00000170 22 02 a9 ff 5e 55 37 6e 61 86 71 73 94 2f 7e 50 |"...^U7na.qs./~P| -00000180 45 96 cf 23 dd 39 90 5d 57 04 a3 d0 9f 97 f8 56 |E..#.9.]W......V| -00000190 fa cf 7a a9 e6 57 1f cb 33 a0 82 7a 84 94 1f 6d |..z..W..3..z...m| -000001a0 d8 0b c7 fb bc 62 94 36 4a d6 96 ce f6 f2 7f 06 |.....b.6J.......| -000001b0 18 59 66 77 77 12 8c 74 06 61 8f b6 37 35 65 fd |.Yfww..t.a..75e.| -000001c0 f1 0b fe e6 cc a9 64 f5 b5 0d 06 4e 38 4b 4b 78 |......d....N8KKx| -000001d0 be 6a cc 67 9e 39 f8 f2 27 33 a9 2d bc 9c 5e 06 |.j.g.9..'3.-..^.| -000001e0 b9 fb 76 0c be 8d 2a a5 6d cf 83 55 4f c5 6e 6e |..v...*.m..UO.nn| -000001f0 d0 08 8b f6 5a 61 17 03 03 00 59 c1 cc 58 14 33 |....Za....Y..X.3| -00000200 5a 39 b5 40 46 e8 b1 28 06 08 22 d3 27 b4 e6 ef |Z9.@F..(..".'...| -00000210 10 79 08 d4 ce 9e e2 cb 0b 86 a4 b1 80 e4 1b ac |.y..............| -00000220 71 15 fd 16 5b aa 01 c2 7b e3 c2 84 01 c0 f6 04 |q...[...{.......| -00000230 a7 31 2b ec f2 50 bf 5a 07 6f b8 03 9f d2 c6 ad |.1+..P.Z.o......| -00000240 73 18 81 f5 fd 9a 5a b2 bc 9f 85 94 9f f6 da da |s.....Z.........| -00000250 dd 56 bc 66 17 03 03 00 35 9f 7e 2e 02 66 bb ac |.V.f....5.~..f..| -00000260 3d d8 92 70 c9 35 c6 df ff 0f 81 b5 ca d4 56 4a |=..p.5........VJ| -00000270 24 06 06 57 28 e9 9d 82 0e 40 06 a7 f8 cc bc 6c |$..W(....@.....l| -00000280 a2 ea 2b 0e 88 77 05 de 3d 30 a0 6f bc 98 |..+..w..=0.o..| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 d1 |..+.....3.$... .| +00000060 41 fa 43 c4 c8 0a 98 e0 da 88 c8 58 36 ab 12 61 |A.C........X6..a| +00000070 d5 2d 9a 5b 10 fd 1f 10 bf d4 df 23 d0 de 2c 14 |.-.[.......#..,.| +00000080 03 03 00 01 01 17 03 03 00 17 bf 64 74 65 06 48 |...........dte.H| +00000090 41 72 b9 9f 41 24 a9 d0 05 00 4e 8c 93 a8 bd 91 |Ar..A$....N.....| +000000a0 ce 17 03 03 01 50 20 58 c1 4f 42 ed e9 e6 50 86 |.....P X.OB...P.| +000000b0 5f 49 88 ac 8b b8 3d 25 1d 87 b5 7f 9f 1a a2 cd |_I....=%........| +000000c0 f2 90 d0 6d 13 ed a6 6c f9 1e af c8 73 dd 68 d4 |...m...l....s.h.| +000000d0 46 1f ce d4 74 87 57 0f c1 b7 dd bd 5a 44 7c 08 |F...t.W.....ZD|.| +000000e0 2d 60 ca 34 1f 94 ee 4a cd e7 4a 69 1c 8d 4c 64 |-`.4...J..Ji..Ld| +000000f0 e8 a1 90 89 75 e2 3b 5b 0e 58 f8 7a 0a fe 2d 6d |....u.;[.X.z..-m| +00000100 ee 82 ab 07 e3 09 ae 37 d5 d6 31 9f 47 a5 eb ca |.......7..1.G...| +00000110 fd d9 5e b3 f1 ab 8a 64 8f 66 7d e7 a5 66 b4 46 |..^....d.f}..f.F| +00000120 3c 3c 2c 2f f7 5a 46 b3 e7 8b a4 3e 5f 21 ab 66 |<<,/.ZF....>_!.f| +00000130 60 4d ca 20 4b 7b 75 5a 88 a5 65 97 1b 70 5b 69 |`M. K{uZ..e..p[i| +00000140 7b 22 87 48 e4 a2 a8 32 06 65 00 91 e6 ac 6c 9b |{".H...2.e....l.| +00000150 42 04 53 f5 e5 46 72 d6 3a 7d d8 c1 e4 f1 79 dc |B.S..Fr.:}....y.| +00000160 de 7b 21 83 d0 98 90 99 2d 9d 78 67 89 31 2a 7d |.{!.....-.xg.1*}| +00000170 6a 97 c7 80 a9 2a 91 4e e2 30 29 96 25 97 e9 94 |j....*.N.0).%...| +00000180 2d 0a e0 30 8c e3 54 00 2a 29 e9 60 ef 4c 60 1c |-..0..T.*).`.L`.| +00000190 76 51 db 5d d7 7c 0c ae f3 a8 9e 3b 49 c6 a7 ce |vQ.].|.....;I...| +000001a0 a3 e8 e6 8c 13 ea fa bd 7f 59 36 06 1e 0c 54 2d |.........Y6...T-| +000001b0 d2 75 8a 75 94 f3 5c 77 0a 8e a0 23 9f 21 d8 ed |.u.u..\w...#.!..| +000001c0 65 87 fa f0 65 e1 81 2b 45 50 91 9e 48 8f 4c 80 |e...e..+EP..H.L.| +000001d0 7a c7 32 07 9a d9 d4 59 7a 7c 11 01 c2 75 fd 25 |z.2....Yz|...u.%| +000001e0 15 7b de b1 72 54 42 9e 02 41 a8 1a 04 6a 64 ba |.{..rTB..A...jd.| +000001f0 97 48 48 48 24 3d 17 03 03 00 59 d7 53 12 64 01 |.HHH$=....Y.S.d.| +00000200 d4 b7 e4 bf e1 33 f6 49 24 cf e8 6f 48 56 d6 1b |.....3.I$..oHV..| +00000210 e3 11 e9 a5 fb 7d f7 f5 b7 06 6c ce 4d e7 3c ca |.....}....l.M.<.| +00000220 bc 30 27 2e 02 4a 50 ec 7e 8c d4 cd 7a 78 43 3f |.0'..JP.~...zxC?| +00000230 5d 17 d7 bd 3e 78 68 21 ad 98 93 ad 90 de f7 c9 |]...>xh!........| +00000240 ab 7d 36 59 7e 7b e8 10 92 de ee 44 a2 e3 df 41 |.}6Y~{.....D...A| +00000250 6c a8 6c 9b 17 03 03 00 35 3a 9b 88 fc 4d 78 aa |l.l.....5:...Mx.| +00000260 a3 96 c7 f9 80 87 75 88 41 e6 58 9c f7 f6 88 0c |......u.A.X.....| +00000270 8f 57 8f 41 b7 49 a9 c2 db d6 44 51 a6 cb eb c3 |.W.A.I....DQ....| +00000280 8d e5 32 19 4b e5 dd 4e 19 6b f4 38 cd 3d |..2.K..N.k.8.=| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 1c 60 8f 01 6b |..........5.`..k| -00000010 7c e3 d4 28 24 d8 7c 85 7f 63 44 23 97 7c a0 de ||..($.|..cD#.|..| -00000020 70 61 9e d9 ce 35 d9 3b 81 68 09 12 c1 b9 5e f5 |pa...5.;.h....^.| -00000030 32 23 9b 47 fc be 74 3c e6 1b 3f cd e8 c1 f1 4f |2#.G..t<..?....O| -00000040 17 03 03 00 17 1a 16 bc fe 99 30 d8 97 c1 00 d9 |..........0.....| -00000050 fd 1a 44 bd 84 35 dc 66 62 eb 28 3d 17 03 03 00 |..D..5.fb.(=....| -00000060 13 b4 8a 54 df ae 97 ce 2e ae fa 38 ca 02 a1 d6 |...T.......8....| -00000070 f5 40 64 2b |.@d+| +00000000 14 03 03 00 01 01 17 03 03 00 35 64 73 84 51 69 |..........5ds.Qi| +00000010 81 4c a7 ce 8b 39 08 0e 0f 25 d2 24 49 3c 9d 98 |.L...9...%.$I<..| +00000020 c7 46 f5 7e ba bd d1 9d 79 d3 f6 cb 29 00 95 90 |.F.~....y...)...| +00000030 c2 fa c6 65 01 f2 9d 12 a7 db 14 49 e6 0b 40 c9 |...e.......I..@.| +00000040 17 03 03 00 17 df ad 2a 5f f7 bd 94 90 dd 11 24 |.......*_......$| +00000050 b8 97 6e fc d3 93 91 47 36 26 2d e1 17 03 03 00 |..n....G6&-.....| +00000060 13 40 ad 3c c3 49 76 47 c0 02 f0 bc 80 66 3c e4 |.@.<.IvG.....f<.| +00000070 35 28 eb b5 |5(..| diff --git a/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial b/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial index 13ae97153af..13fb6048748 100644 --- a/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial +++ b/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,85 +7,86 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 48 e6 a7 a9 4c |....z...v..H...L| -00000010 c3 a7 cc 18 b7 71 7d ed c5 6a cb ca b5 9f 00 fd |.....q}..j......| -00000020 f8 2c ac 9c 1f 24 27 b9 c6 55 8e 20 00 00 00 00 |.,...$'..U. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 67 c5 21 e2 8b |....z...v..g.!..| +00000010 b6 6a cc 42 40 24 b2 4f 55 61 d9 20 78 e2 e3 40 |.j.B@$.OUa. x..@| +00000020 83 62 3d 08 e3 0a 31 0b 55 f5 b6 20 00 00 00 00 |.b=...1.U.. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 dd |..+.....3.$... .| -00000060 be 27 eb a0 9c b1 22 6a 8c 29 9a d4 47 c2 ee 14 |.'...."j.)..G...| -00000070 39 0c 60 81 c9 06 3f dc e5 e0 24 9a c4 88 35 14 |9.`...?...$...5.| -00000080 03 03 00 01 01 17 03 03 00 17 25 70 5a e5 6b 9e |..........%pZ.k.| -00000090 56 b9 cf 83 48 b0 bc 99 6a 86 e1 cb 4e ce b5 10 |V...H...j...N...| -000000a0 e0 17 03 03 02 6d c7 a6 79 ef b0 81 d6 e4 0e 02 |.....m..y.......| -000000b0 59 32 88 cc b1 0d 53 f6 33 9b d2 e8 74 a9 0a a7 |Y2....S.3...t...| -000000c0 f9 76 e9 6e 0d 16 75 0b e0 8f 5c b5 31 47 6b 68 |.v.n..u...\.1Gkh| -000000d0 52 c7 c2 84 cb 48 81 a3 da bd a1 50 5c ec 5c a7 |R....H.....P\.\.| -000000e0 10 01 58 cc 03 c3 53 04 03 69 80 f4 ad 4d ce 72 |..X...S..i...M.r| -000000f0 26 4e 6c c7 2c 31 69 2b fd 97 67 5e 7d e0 05 b3 |&Nl.,1i+..g^}...| -00000100 f4 40 64 a1 bd a3 fd a8 f9 7b 18 82 89 8f 25 f9 |.@d......{....%.| -00000110 ca ca c4 8f e4 90 7b 26 7a d5 b2 1e fa 05 db ad |......{&z.......| -00000120 8a 9f 93 e9 13 5b 28 cc cb 8b 30 f2 4c 1d 73 09 |.....[(...0.L.s.| -00000130 7f 6b 63 5c 29 36 2f fc a5 6e eb 24 79 f8 7c 63 |.kc\)6/..n.$y.|c| -00000140 1f ef 41 72 98 69 7c d6 8d f9 76 d4 4d af b0 71 |..Ar.i|...v.M..q| -00000150 2e f7 f8 b5 73 45 05 52 fa 25 46 02 28 0d d9 7a |....sE.R.%F.(..z| -00000160 60 13 b9 6c 6d fb f3 be e3 04 74 76 72 d6 a4 91 |`..lm.....tvr...| -00000170 d1 2c 0d 1e fa 23 ef c7 80 ff 1e aa 1b af 50 58 |.,...#........PX| -00000180 77 ea 49 d9 22 4d ed bc bf a6 0a 41 8e e7 5b 31 |w.I."M.....A..[1| -00000190 de 33 05 10 46 a5 54 aa 5e 90 5c 15 64 2d 1b e9 |.3..F.T.^.\.d-..| -000001a0 5c fc 93 8d 2f b2 af 74 d7 d2 c6 7f 27 68 fd 44 |\.../..t....'h.D| -000001b0 13 60 70 87 e8 08 e1 e2 af 7f 1a 2c 29 5f 45 fe |.`p........,)_E.| -000001c0 49 9a d0 42 c9 51 ef f7 5b ae 02 df 27 1c 29 20 |I..B.Q..[...'.) | -000001d0 35 4f 3d 7d 74 97 0c 20 be f8 a3 c9 b7 ff 65 69 |5O=}t.. ......ei| -000001e0 08 89 92 fe 85 65 9f 8a 00 4b 9f 39 8d 6f 29 7c |.....e...K.9.o)|| -000001f0 7c e9 16 e4 bd 06 a3 b0 5b 7f cf f0 74 14 56 a2 ||.......[...t.V.| -00000200 76 61 b8 79 10 44 55 4f 25 55 a7 be a4 eb 2e 7d |va.y.DUO%U.....}| -00000210 9a b8 7a d8 d7 34 b6 ef 6c f7 fb ef fd 16 c2 61 |..z..4..l......a| -00000220 89 bb 98 22 c6 80 9e 33 7f e9 35 7a 58 b6 33 1c |..."...3..5zX.3.| -00000230 d6 87 68 b7 62 21 3b 26 9b f1 b1 f2 92 d5 4b 19 |..h.b!;&......K.| -00000240 02 58 05 3c 81 cf 00 5a 54 86 a5 61 8f 71 ae 32 |.X.<...ZT..a.q.2| -00000250 f2 0f 08 3b 13 4d f3 e6 03 2e 73 9c 50 4a b7 6c |...;.M....s.PJ.l| -00000260 d8 0a 04 fc b5 44 a5 45 c8 86 c9 9f 29 b4 00 90 |.....D.E....)...| -00000270 d8 8b e0 c8 ba 63 9f 42 65 ef ba 5b dc b2 61 53 |.....c.Be..[..aS| -00000280 e6 4b 29 72 51 c9 21 d4 d7 2d 14 56 82 80 32 36 |.K)rQ.!..-.V..26| -00000290 fd 72 b6 16 6f 06 71 f9 60 4f 32 ce f6 83 94 75 |.r..o.q.`O2....u| -000002a0 d9 23 d3 41 f8 e7 90 60 80 a8 a5 95 c0 a2 dd 2e |.#.A...`........| -000002b0 e7 60 73 5b c0 a5 a0 bd 8b bc cc 32 8a 9e 30 6a |.`s[.......2..0j| -000002c0 72 2f 61 24 56 0b 1e 3e 52 92 d2 e0 11 cd 52 69 |r/a$V..>R.....Ri| -000002d0 c4 73 7f 72 95 fd f5 c4 72 d7 77 73 85 bf be e0 |.s.r....r.ws....| -000002e0 cd 3c 3b 3d 92 63 91 ba c8 a8 d2 32 40 6a 33 91 |.<;=.c.....2@j3.| -000002f0 c0 71 fe ea 76 9f a9 96 dc c0 a9 bd 67 b6 23 42 |.q..v.......g.#B| -00000300 d9 1b 3d 8d d4 5f 81 38 74 1c db 36 9e bd 79 fd |..=.._.8t..6..y.| -00000310 30 c5 db 17 03 03 00 99 61 1e 25 cb 11 26 61 72 |0.......a.%..&ar| -00000320 a0 9a de 5b ad 5b ad 8a 29 43 eb 76 5a 16 a4 d3 |...[.[..)C.vZ...| -00000330 d4 a1 84 e4 7e a1 2b 76 75 b6 a5 a6 36 da d3 bf |....~.+vu...6...| -00000340 0c 3a 39 ca ef 3f 02 22 63 3d 5d c1 30 94 ba 32 |.:9..?."c=].0..2| -00000350 fe c0 20 c1 ba c8 fa 29 e8 1c c6 ab f0 c9 53 a4 |.. ....)......S.| -00000360 73 d0 9a 2d 50 d8 b4 0c db e5 4a 9f 98 38 34 c9 |s..-P.....J..84.| -00000370 9f ff 63 a9 50 7b 26 00 64 26 4d 0d 20 d5 e5 27 |..c.P{&.d&M. ..'| -00000380 e1 41 7b 5a 03 97 0a 14 8c 55 3c 45 4b 72 ce de |.A{Z.....U...,..N.....| +000001e0 6b 24 30 5d f8 a0 52 ca 02 9a 50 58 43 b6 22 04 |k$0]..R...PXC.".| +000001f0 47 c6 ba 1c e1 aa c2 2c ca 50 13 de 2b 2b 34 ec |G......,.P..++4.| +00000200 80 8c 34 77 20 ab f3 f3 42 d2 9a 2b 9d 38 32 f9 |..4w ...B..+.82.| +00000210 de 9c 7b ee 22 4f 41 9e ea 35 88 8c e7 74 f6 ac |..{."OA..5...t..| +00000220 a5 fe af d9 c4 b1 a4 87 aa 9f d9 02 3b 4b 92 2b |............;K.+| +00000230 f4 ea 6f 81 b8 54 ca 77 3d a2 37 f0 60 d8 26 e4 |..o..T.w=.7.`.&.| +00000240 27 04 c8 5b bf bc 5e 9c 8b a9 f6 c1 58 31 de 48 |'..[..^.....X1.H| +00000250 67 5b c5 d7 ae 35 cc d8 8d 01 9b e0 d0 c7 33 f8 |g[...5........3.| +00000260 36 c1 e8 50 32 27 87 6c 64 71 27 3f 66 82 fa 92 |6..P2'.ldq'?f...| +00000270 d3 fe b9 9e d3 e2 63 43 64 13 73 4b e9 34 d9 ae |......cCd.sK.4..| +00000280 49 dd 9c 17 f3 a6 34 27 3e 07 68 ed 6b 98 0a 69 |I.....4'>.h.k..i| +00000290 9c f5 4f 1e fc ac 72 08 7e bb bd 97 fe f9 c1 09 |..O...r.~.......| +000002a0 a2 69 75 c4 e7 a1 83 df 03 0f 74 21 e8 4c 4c d7 |.iu.......t!.LL.| +000002b0 a2 90 5a 4d d9 a2 fa f1 e4 dc ff 75 e8 fe a1 91 |..ZM.......u....| +000002c0 46 a4 c2 0b c3 9e 83 45 40 b4 ba fe ed 9e 3a 81 |F......E@.....:.| +000002d0 a9 27 b9 fa 6f 9e 38 10 2f e6 05 9a 00 43 e9 fb |.'..o.8./....C..| +000002e0 60 b8 26 2e 18 4a 0c 14 6a 9f aa 26 1d 53 9e 4f |`.&..J..j..&.S.O| +000002f0 fc 7e e1 90 60 28 b1 89 db b6 68 58 5d 2a fa 43 |.~..`(....hX]*.C| +00000300 91 99 c1 94 74 77 a9 30 cf 1e 9d 49 fc cd be 6c |....tw.0...I...l| +00000310 5a 72 90 17 03 03 00 99 1b 1f 16 9b 8e 85 5a 8a |Zr............Z.| +00000320 3c c7 d8 e5 86 20 eb 71 83 12 e7 3b 02 ca a1 18 |<.... .q...;....| +00000330 aa b7 ef 67 9d bf 57 46 14 3b ed b2 9b 2e f1 96 |...g..WF.;......| +00000340 67 b0 cc 20 ab 67 63 5c a9 96 d8 22 8e fa f0 94 |g.. .gc\..."....| +00000350 1e 83 6c 53 8a 75 a5 37 1d f1 de 1f a7 22 13 08 |..lS.u.7....."..| +00000360 b7 13 dd 25 26 eb 7a 85 72 33 ed a8 27 be cc ff |...%&.z.r3..'...| +00000370 8d 42 fa 6a f8 0a 59 44 6f 48 4d 58 27 d5 28 fb |.B.j..YDoHMX'.(.| +00000380 37 b0 85 25 49 d0 32 7c dd b8 46 1a aa dc 16 b7 |7..%I.2|..F.....| +00000390 f2 fd 99 17 67 41 c0 2d 75 0d 66 ef 65 e2 5f af |....gA.-u.f.e._.| +000003a0 d8 b4 aa 15 1c 24 40 0d 0d 4f a8 bc c9 92 1c ab |.....$@..O......| +000003b0 91 17 03 03 00 35 f9 69 7e 2a d6 fa 6e 42 25 6c |.....5.i~*..nB%l| +000003c0 da 96 f7 79 5f 02 44 1f d8 1c a2 41 fc eb a5 12 |...y_.D....A....| +000003d0 bf 37 ab b0 40 92 55 50 64 8e 7b e9 e5 f3 04 b5 |.7..@.UPd.{.....| +000003e0 0f 04 93 98 fa ca 24 69 a1 73 26 |......$i.s&| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 a6 7f ef 71 68 |..........5...qh| -00000010 8b 86 84 20 a6 e7 65 3f 3f f8 c6 8b 62 40 31 e2 |... ..e??...b@1.| -00000020 1a ee 8d 0a 64 88 ea 4b 83 5f c5 ff 1b 9d aa 5f |....d..K._....._| -00000030 ce a4 31 76 06 90 da ad b9 17 49 0b a6 b5 37 80 |..1v......I...7.| -00000040 17 03 03 00 17 2b be e8 98 11 37 0d db 46 69 0d |.....+....7..Fi.| -00000050 51 34 ee 13 00 c3 f1 12 8a 13 21 b7 17 03 03 00 |Q4........!.....| -00000060 13 8d ec 94 6f 55 b1 d5 c0 d6 a3 6e a2 8d 67 76 |....oU.....n..gv| -00000070 7b c7 b8 1d |{...| +00000000 14 03 03 00 01 01 17 03 03 00 35 80 f8 9b f1 1d |..........5.....| +00000010 89 31 a8 ea b8 cc 44 a7 6c c3 f7 ea 0f fd f4 a3 |.1....D.l.......| +00000020 4c c2 15 06 bd 79 16 90 a1 bf 44 df e5 21 03 ff |L....y....D..!..| +00000030 e5 83 08 67 70 09 11 21 8e 96 47 e6 f4 e3 36 6e |...gp..!..G...6n| +00000040 17 03 03 00 17 7b 87 be 4e f8 ce 6f 30 b8 5b 95 |.....{..N..o0.[.| +00000050 20 79 23 f7 50 6b 17 b8 13 a2 38 6a 17 03 03 00 | y#.Pk....8j....| +00000060 13 2a d5 e0 a4 17 7d 4f 3b 5a 6c bc 9d 5a 79 5b |.*....}O;Zl..Zy[| +00000070 a8 f6 b2 4a |...J| diff --git a/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest b/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest index a669920d938..4d58f8d440d 100644 --- a/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest +++ b/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 14 01 00 01 10 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,14 +7,16 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7b 00 0b 00 02 01 00 ff 01 00 01 00 00 |...{............| +00000080 01 00 00 95 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| -000000a0 00 0a 00 06 00 04 00 1d 00 17 00 0d 00 1a 00 18 |................| +000000a0 00 0a 00 06 00 04 00 1d 00 17 00 0d 00 16 00 14 |................| 000000b0 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 01 |................| -000000c0 05 03 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 |.........+......| -000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| -000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| -000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +000000c0 05 03 06 03 00 32 00 1a 00 18 08 04 04 03 08 07 |.....2..........| +000000d0 08 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01 |................| +000000e0 02 03 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| +000000f0 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 |3.&.$... /.}.G.b| +00000100 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +00000110 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| >>> Flow 2 (server to client) 00000000 16 03 03 00 58 02 00 00 54 03 03 cf 21 ad 74 e5 |....X...T...!.t.| 00000010 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a |.a......e......z| @@ -24,7 +26,7 @@ 00000050 0c 00 2b 00 02 03 04 00 33 00 02 00 17 14 03 03 |..+.....3.......| 00000060 00 01 01 |...| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 16 03 03 01 1b 01 00 01 17 03 |................| +00000000 14 03 03 00 01 01 16 03 03 01 35 01 00 01 31 03 |..........5...1.| 00000010 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............| @@ -32,88 +34,89 @@ 00000050 00 00 00 32 cc a9 cc a8 c0 2b c0 2f c0 2c c0 30 |...2.....+./.,.0| 00000060 c0 09 c0 13 c0 0a c0 14 00 9c 00 9d 00 2f 00 35 |............./.5| 00000070 c0 12 00 0a c0 23 c0 27 00 3c c0 07 c0 11 00 05 |.....#.'.<......| -00000080 13 03 13 01 13 02 01 00 00 9c 00 0b 00 02 01 00 |................| +00000080 13 03 13 01 13 02 01 00 00 b6 00 0b 00 02 01 00 |................| 00000090 ff 01 00 01 00 00 17 00 00 00 12 00 00 00 05 00 |................| 000000a0 05 01 00 00 00 00 00 0a 00 06 00 04 00 1d 00 17 |................| -000000b0 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 |................| -000000c0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 2b |...............+| -000000d0 00 09 08 03 04 03 03 03 02 03 01 00 33 00 47 00 |............3.G.| -000000e0 45 00 17 00 41 04 1e 18 37 ef 0d 19 51 88 35 75 |E...A...7...Q.5u| -000000f0 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e b2 |q..T[....g..$ >.| -00000100 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c 4b |V...(^.+-O....lK| -00000110 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a 41 |[.V.2B.X..I..h.A| -00000120 03 56 6b dc 5a 89 |.Vk.Z.| +000000b0 00 0d 00 16 00 14 08 04 04 03 08 07 08 05 08 06 |................| +000000c0 04 01 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 |...........2....| +000000d0 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 01 |................| +000000e0 05 03 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 |.........+......| +000000f0 03 03 02 03 01 00 33 00 47 00 45 00 17 00 41 04 |......3.G.E...A.| +00000100 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000110 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000120 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000130 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| >>> Flow 4 (server to client) -00000000 16 03 03 00 9b 02 00 00 97 03 03 9a 1f 7a fa 06 |.............z..| -00000010 c4 5f 92 61 62 d2 a5 f3 ae b9 a6 d8 6b eb 13 a7 |._.ab.......k...| -00000020 2f 17 62 79 3a ca 42 8b 18 06 15 20 00 00 00 00 |/.by:.B.... ....| +00000000 16 03 03 00 9b 02 00 00 97 03 03 3e b5 60 d1 cd |...........>.`..| +00000010 f5 a6 76 2c bd 49 f6 0f c2 ff ff 6b c9 f6 45 19 |..v,.I.....k..E.| +00000020 f6 e3 e7 fc 31 8b 49 4e 88 29 55 20 00 00 00 00 |....1.IN.)U ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| -00000060 d1 56 18 67 59 a5 e1 ed 99 0f ca e5 6b 5f e3 d9 |.V.gY.......k_..| -00000070 e3 fd e6 a2 50 93 bf 87 85 60 e7 7f 0b a0 96 c4 |....P....`......| -00000080 29 55 63 de fe 6b 75 99 b2 a6 75 92 61 d0 96 19 |)Uc..ku...u.a...| -00000090 f5 60 8f ec e9 d3 98 4a b9 6b 98 26 c1 3e 27 7e |.`.....J.k.&.>'~| -000000a0 17 03 03 00 17 5a aa bb 35 67 ec 83 da 8e 85 bd |.....Z..5g......| -000000b0 ae a5 0d c9 8b cd 03 bf 96 2b 35 61 17 03 03 02 |.........+5a....| -000000c0 6d 85 0c 7c d5 ff 0f 77 0a a4 b7 97 aa d3 f7 af |m..|...w........| -000000d0 4b 58 cb 24 4d 9f a6 d8 e2 c3 10 ce 3a 5d e4 cc |KX.$M.......:]..| -000000e0 84 7d 1f 71 bd b6 25 0c 10 75 d3 8d b6 12 04 56 |.}.q..%..u.....V| -000000f0 63 af 53 e5 cc 29 ce f7 18 7a 93 91 73 ae ff c1 |c.S..)...z..s...| -00000100 2e 2b 3d 76 ab 99 c8 e0 fd 69 b3 67 39 e9 58 40 |.+=v.....i.g9.X@| -00000110 4a 63 e8 71 c5 8d de 44 fb ef 4d 0a dc ae 51 12 |Jc.q...D..M...Q.| -00000120 7e ea 6a 25 32 8e 5b 08 6e c7 b2 87 00 4e 35 d8 |~.j%2.[.n....N5.| -00000130 cd 3b bd 8c dc e8 55 a9 2f 65 d1 7f c1 28 33 f9 |.;....U./e...(3.| -00000140 70 e1 af d8 2d 64 4c ac 5a 3a 16 6d 3e 97 a7 0e |p...-dL.Z:.m>...| -00000150 cd 28 05 1c ea 28 8d 63 a3 41 e2 3a 24 27 f4 43 |.(...(.c.A.:$'.C| -00000160 97 c8 89 09 ed 8b 96 74 b3 dc 98 f4 0c c2 6f 25 |.......t......o%| -00000170 fc 30 8a f8 25 49 e1 91 fb c6 39 23 ca d5 16 08 |.0..%I....9#....| -00000180 5f bf 10 88 71 a4 c5 ac e7 ad 9e 5a 4d e8 d3 1f |_...q......ZM...| -00000190 f0 5d 83 9d c9 e2 b3 f8 e4 a3 a5 57 5d ca 30 74 |.].........W].0t| -000001a0 a6 1b c7 51 50 05 5f 7e 93 71 1a 8d fc 04 d6 fe |...QP._~.q......| -000001b0 4e 4b 95 54 18 43 19 4d d2 dc 81 a8 94 76 7e 23 |NK.T.C.M.....v~#| -000001c0 56 8c 86 f9 15 d2 a8 0c 48 4e 0e 81 df e0 31 52 |V.......HN....1R| -000001d0 c9 2e b4 39 f3 cf ae e2 29 72 01 ed 34 4f 09 ce |...9....)r..4O..| -000001e0 64 de a9 9b 84 61 3a bb 0b ac 4e b1 6d 37 41 10 |d....a:...N.m7A.| -000001f0 5b cf 99 b1 3e e6 f5 7b 1c d4 d0 d5 34 fc ab c6 |[...>..{....4...| -00000200 29 8e 0b 53 e4 7b 35 33 e4 e3 f6 77 9b f6 c6 ae |)..S.{53...w....| -00000210 73 3c c5 80 c8 72 f7 56 6c 4c ce e5 a7 05 63 ee |s<...r.VlL....c.| -00000220 07 e0 1d 3e 73 3e 55 73 ba 63 a8 d7 99 6a 48 57 |...>s>Us.c...jHW| -00000230 0c 55 51 42 4b 27 91 4b 75 b3 3b 4c 29 f1 52 e8 |.UQBK'.Ku.;L).R.| -00000240 85 f9 49 53 ed 87 6d 9e 8f 5c 29 7c 5c 9c 4e 9a |..IS..m..\)|\.N.| -00000250 90 a8 99 2a 53 65 f7 d9 61 ef 6a 56 2a da 76 ed |...*Se..a.jV*.v.| -00000260 04 84 11 f5 1c 40 82 52 7d fa 00 79 43 12 42 b4 |.....@.R}..yC.B.| -00000270 ca 7a 86 d5 8d d6 c5 7b 04 13 79 08 72 0c ce d7 |.z.....{..y.r...| -00000280 88 9a f2 2c b5 9a 18 a4 d2 87 48 ce ab 17 33 fd |...,......H...3.| -00000290 cf 22 3c 72 03 86 af 35 2a b3 fe 24 0e 86 d8 82 |."......D..| -000002c0 14 12 cd 16 e5 6a 58 1b 3f f8 70 d6 47 e6 1b 98 |.....jX.?.p.G...| -000002d0 74 9c 21 2b 6d f8 8a 47 05 86 b1 fa 63 9d cc 19 |t.!+m..G....c...| -000002e0 da 9a a0 ea 5a 26 98 e6 b7 d0 da 03 b3 1d 33 e8 |....Z&........3.| -000002f0 55 74 ee 4b 6a 06 0f f1 45 35 72 81 bb c9 61 4e |Ut.Kj...E5r...aN| -00000300 60 d6 83 e6 ab 08 77 a4 f9 73 e5 d8 cb 66 9f 41 |`.....w..s...f.A| -00000310 00 15 2c 09 0e ad 16 02 6c 06 5f bc bf 47 f1 5a |..,.....l._..G.Z| -00000320 85 97 ab 88 e8 45 b0 31 96 ad 56 00 97 59 17 03 |.....E.1..V..Y..| -00000330 03 00 99 5e 77 80 46 1d 2f 47 9f b3 43 4d a6 2b |...^w.F./G..CM.+| -00000340 e9 f7 72 a2 d0 c6 69 7c df 5d ce a0 3b 89 e2 69 |..r...i|.]..;..i| -00000350 e7 35 5e 00 fb 87 10 4a a8 41 02 b7 89 fa 88 fc |.5^....J.A......| -00000360 72 63 ce bf 41 61 16 91 55 06 cd b6 fa 78 09 bc |rc..Aa..U....x..| -00000370 f6 21 a0 c2 1f f3 fa 34 2a 9e b9 8a 0c 72 81 02 |.!.....4*....r..| -00000380 66 a7 da 6b d6 e2 aa 99 6d 4b 42 f5 19 83 52 89 |f..k....mKB...R.| -00000390 9a 26 56 5d d5 a4 a7 bd ad b4 10 db ee 87 1d 15 |.&V]............| -000003a0 15 df 30 95 d8 61 e2 c4 88 47 e1 91 e3 85 33 fe |..0..a...G....3.| -000003b0 7d 02 0c 22 6b 52 22 a7 cf bf bf f0 9d 25 65 e0 |}.."kR"......%e.| -000003c0 6b da a2 8c 9a 00 3d 68 78 55 38 69 17 03 03 00 |k.....=hxU8i....| -000003d0 35 c8 ca 51 96 aa c1 4b a0 09 d3 bc d9 ea 35 db |5..Q...K......5.| -000003e0 f2 8d bb ab b3 23 09 a1 d1 9c 40 3e e4 84 d3 1c |.....#....@>....| -000003f0 60 64 5c ff 01 c7 78 69 c2 4a fb e1 c3 d6 f0 57 |`d\...xi.J.....W| -00000400 fa 3a 5f 7a 8b 70 |.:_z.p| +00000060 f8 a5 4d 81 0a 05 43 42 0b d6 ca 3b 3e 02 44 20 |..M...CB...;>.D | +00000070 56 89 80 d3 03 50 1a b4 70 50 78 aa 81 2b 5b 03 |V....P..pPx..+[.| +00000080 6c 38 22 c1 17 4f e5 b9 57 ab 58 33 76 8e ae c9 |l8"..O..W.X3v...| +00000090 a0 74 47 a0 10 c0 5c a7 8c 77 24 c8 90 bb f4 2a |.tG...\..w$....*| +000000a0 17 03 03 00 17 0c 2a 67 cb 9f a8 e8 5b 97 4a 75 |......*g....[.Ju| +000000b0 24 80 65 28 15 a7 d4 71 eb 24 74 7e 17 03 03 02 |$.e(...q.$t~....| +000000c0 6d 89 a3 fa 0f a6 dd dc b5 5a f9 03 93 5a 2a a6 |m........Z...Z*.| +000000d0 2f 65 81 9e 0d 2c 21 25 0b 7c 04 41 40 3e 95 a4 |/e...,!%.|.A@>..| +000000e0 31 21 2a 08 db 35 bc 5a 93 aa b4 8f 30 28 0c e5 |1!*..5.Z....0(..| +000000f0 11 f6 31 d6 7a b0 df 9c f3 76 30 72 e2 27 1c d3 |..1.z....v0r.'..| +00000100 75 68 3d 63 71 27 da 72 7a 18 19 da 25 94 ee e3 |uh=cq'.rz...%...| +00000110 62 6f 45 c5 38 67 ba 4a 1f 6f f3 ea 46 c6 09 ad |boE.8g.J.o..F...| +00000120 db 3c 42 3c d7 8d 9c 49 8d 2c 22 15 74 98 60 5b |...| +00000190 c6 b2 c3 eb ec 03 7d d2 85 2b c3 7f e7 07 c1 50 |......}..+.....P| +000001a0 c9 b6 6f ab 7a 86 7b b3 fd 8b 9a 6a 3c ea 18 06 |..o.z.{....j<...| +000001b0 13 e4 a4 9b d0 2c ef 8c 3f ea 8e d8 c4 d4 54 33 |.....,..?.....T3| +000001c0 2e e5 b6 40 85 a8 4b 5d 9b 3c f2 9e 70 5a 23 d7 |...@..K].<..pZ#.| +000001d0 c1 e1 b4 7a 42 69 fb b1 49 99 cf 60 5c 8a c0 7f |...zBi..I..`\...| +000001e0 c2 8c 8c 26 4f 0f 6c 10 bd e4 51 ab 19 4d 2a 63 |...&O.l...Q..M*c| +000001f0 b3 39 1e d6 55 00 c9 89 3a c0 5a 2b 5b 0a e9 10 |.9..U...:.Z+[...| +00000200 56 4c 8a 88 2d 37 27 50 07 2a 77 19 92 6a a0 67 |VL..-7'P.*w..j.g| +00000210 c9 34 e7 b2 e4 f8 f8 fc e0 24 c1 8e 6a 04 b0 6a |.4.......$..j..j| +00000220 35 1b 5a 74 78 34 81 09 d5 ed bc 61 55 bd bf 6f |5.Ztx4.....aU..o| +00000230 e4 a1 13 e9 b1 9a de de 54 3b 99 19 f7 90 74 be |........T;....t.| +00000240 48 b0 80 92 e7 19 91 17 12 12 9a 08 77 bf 2c 21 |H...........w.,!| +00000250 33 51 9a 02 fc 8c c5 7b 90 52 89 61 df 64 1f af |3Q.....{.R.a.d..| +00000260 1e 49 2a 7b 33 1b 47 df 34 7f aa ca e3 16 2d 28 |.I*{3.G.4.....-(| +00000270 94 cc 07 d1 0d 1a 07 80 a4 c6 cc 10 a7 72 58 bc |.............rX.| +00000280 65 92 de a1 c7 8b e5 63 9a 83 85 eb ee e8 8d e9 |e......c........| +00000290 63 06 f0 6d 14 81 5a d5 a6 1b 84 d3 a2 5d f1 94 |c..m..Z......]..| +000002a0 a4 af f7 eb 85 d3 00 41 12 b3 bc bf 4a 1a c1 c0 |.......A....J...| +000002b0 b0 46 38 63 f4 05 de e0 c2 b7 ee 5b f8 c8 6c e7 |.F8c.......[..l.| +000002c0 fe a4 3d a2 52 e8 25 4c d0 b4 dd 1a aa e4 9c 5b |..=.R.%L.......[| +000002d0 3c 5c 9b 0f e2 ca 18 a8 59 1d 22 d8 2d cb ca 0d |<\......Y.".-...| +000002e0 61 f0 8e be 55 5e 0b b4 72 2f 32 f1 47 fe b8 94 |a...U^..r/2.G...| +000002f0 ec 14 af c4 59 dd f9 b1 1b 18 84 44 54 c0 16 f0 |....Y......DT...| +00000300 f4 e6 19 82 fb 00 84 6e c0 87 05 82 33 7b 62 d8 |.......n....3{b.| +00000310 e3 83 86 55 d6 06 bd e5 a3 1c c0 f1 ef b3 ae 2c |...U...........,| +00000320 f7 6e fa 9a 3d 6c cf de 5d 77 54 08 03 0c 17 03 |.n..=l..]wT.....| +00000330 03 00 99 03 00 b3 cc ca 76 27 18 16 0a 8e d0 81 |........v'......| +00000340 32 5d 9e 32 75 5e bb b4 c5 5c 6b 61 62 38 3d 2e |2].2u^...\kab8=.| +00000350 21 1a 93 c9 fc b7 90 74 17 78 ae 18 78 86 fc 6d |!......t.x..x..m| +00000360 0b 0c 50 d3 a6 5a 98 a8 76 6f ff 3b 98 f5 2f 11 |..P..Z..vo.;../.| +00000370 3d af 84 92 04 42 93 33 33 5c 9a f2 fc 5f 05 dd |=....B.33\..._..| +00000380 89 a8 c3 c1 e7 92 0f 76 3a ed da 7c 25 e0 96 89 |.......v:..|%...| +00000390 27 97 c1 3e 27 70 3f a4 15 f3 24 6a 47 43 7f d7 |'..>'p?...$jGC..| +000003a0 70 b9 7b 2d 3d 53 c0 f6 53 85 fb f7 62 4a 01 8e |p.{-=S..S...bJ..| +000003b0 3e 30 3b b4 79 17 af 2e 73 56 e5 de ba 48 0e 0c |>0;.y...sV...H..| +000003c0 e0 d3 0a 80 07 b9 53 f1 1d a6 cf 29 17 03 03 00 |......S....)....| +000003d0 35 f8 8f 94 ec 0a b9 d9 b1 2c d3 02 c9 0b ef 19 |5........,......| +000003e0 89 ee a9 c0 b1 f3 9c 87 09 0e fb 9a e2 ad 4a 1e |..............J.| +000003f0 16 6d 84 af b3 fa b9 af 98 79 54 7d 45 29 99 85 |.m.......yT}E)..| +00000400 8c a9 69 b6 ee 4e |..i..N| >>> Flow 5 (client to server) -00000000 17 03 03 00 35 24 4a 53 55 49 92 7a 21 a2 db 69 |....5$JSUI.z!..i| -00000010 e5 2b 00 29 83 cb 91 32 17 48 73 96 89 d1 b2 11 |.+.)...2.Hs.....| -00000020 c4 23 48 41 eb df eb 5a 10 c2 78 4e a2 e4 f0 38 |.#HA...Z..xN...8| -00000030 4a 1c b6 d3 bb 52 bc 7e f6 94 17 03 03 00 17 74 |J....R.~.......t| -00000040 04 34 8d 27 19 da f3 d8 14 30 1b 85 ad 1e 99 cd |.4.'.....0......| -00000050 06 f0 a3 50 94 48 17 03 03 00 13 ac 8f 7e 2e 9c |...P.H.......~..| -00000060 90 96 db 33 e2 e9 94 c1 c9 95 f2 7a d1 8f |...3.......z..| +00000000 17 03 03 00 35 4c c3 af 0b 49 46 e0 51 3a 73 a8 |....5L...IF.Q:s.| +00000010 28 46 95 22 ef d7 05 8a fc 4f 12 98 2f 09 ca a9 |(F.".....O../...| +00000020 4d b8 17 e4 15 15 b5 13 3f 1a cb 8e 3d 19 00 d6 |M.......?...=...| +00000030 19 af 90 66 0e 93 d4 22 4d 54 17 03 03 00 17 56 |...f..."MT.....V| +00000040 31 7c 05 02 1d 84 64 d0 32 21 8d c1 61 7e 7f ce |1|....d.2!..a~..| +00000050 d3 45 b2 df ba df 17 03 03 00 13 3a 57 b6 2e 79 |.E.........:W..y| +00000060 96 09 e9 66 f2 85 7a 21 88 45 cc b4 ff 12 |...f..z!.E....| diff --git a/crypto/tls/testdata/Client-TLSv13-KeyUpdate b/crypto/tls/testdata/Client-TLSv13-KeyUpdate index 1b8004ad0a0..7d04d95a272 100644 --- a/crypto/tls/testdata/Client-TLSv13-KeyUpdate +++ b/crypto/tls/testdata/Client-TLSv13-KeyUpdate @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 18 01 00 01 14 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,97 +7,98 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 99 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| -000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| -000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| -000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| -000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| -000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| -00000100 cb 3b 74 |.;t| +000000b0 00 16 00 14 08 04 04 03 08 07 08 05 08 06 04 01 |................| +000000c0 05 01 06 01 05 03 06 03 00 32 00 1a 00 18 08 04 |.........2......| +000000d0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| +000000e0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| +000000f0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| +00000100 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| +00000110 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 dc 81 c4 82 2e |....z...v.......| -00000010 a2 4f c4 c2 53 c2 bc 6a bd f3 46 84 b5 ba 66 b5 |.O..S..j..F...f.| -00000020 8b 67 7c 90 51 40 12 39 18 e1 bf 20 00 00 00 00 |.g|.Q@.9... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 b2 4e f2 da 8b |....z...v...N...| +00000010 79 31 33 74 d5 37 8e 44 9d ad 6f 91 c4 bb 5d d4 |y13t.7.D..o...].| +00000020 fd f1 e2 42 50 43 f5 3c 7f cf 92 20 00 00 00 00 |...BPC.<... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 3b |..+.....3.$... ;| -00000060 6b 2a e6 c2 7e b6 59 68 e4 e3 f2 f3 14 e5 72 bc |k*..~.Yh......r.| -00000070 c9 61 b4 b0 0a c6 41 0d a9 8e d9 9b 7d 2a 11 14 |.a....A.....}*..| -00000080 03 03 00 01 01 17 03 03 00 17 43 af 38 b9 56 06 |..........C.8.V.| -00000090 2d 10 e3 e5 1d 1b 1e a9 5f 90 ca 0d a9 52 33 86 |-......._....R3.| -000000a0 85 17 03 03 02 6d ac 6a a1 8f 42 27 74 80 25 f9 |.....m.j..B't.%.| -000000b0 1f 48 49 2d c2 33 38 e7 93 7e b0 b2 50 b8 6a ea |.HI-.38..~..P.j.| -000000c0 a6 81 ef 9b 55 83 4e 93 df 92 97 6f 00 f5 c4 fc |....U.N....o....| -000000d0 ec b1 19 dd 68 b5 bd c4 bb ba 63 9a e4 c9 24 af |....h.....c...$.| -000000e0 88 13 65 11 bf ea d9 07 e9 46 fd 5b 60 ce 57 46 |..e......F.[`.WF| -000000f0 8b a9 bd c6 58 1a 3b bd 5e fb 0f 46 ec fc 8b 2c |....X.;.^..F...,| -00000100 ea a7 19 06 6a e5 6f 10 7a 27 04 6b aa a4 2c f4 |....j.o.z'.k..,.| -00000110 ef 3b e8 8a 51 88 fd e0 ae 33 b1 4c b3 04 5e 91 |.;..Q....3.L..^.| -00000120 b0 98 0b 9f 38 a3 3c fb 9f d5 d2 36 e4 09 19 18 |....8.<....6....| -00000130 a5 b3 12 aa c9 03 ac b5 ab bb f1 7a 02 d2 dd 75 |...........z...u| -00000140 0e cb 60 09 39 23 c3 b2 c1 8e e0 18 57 72 54 61 |..`.9#......WrTa| -00000150 4c 99 35 1d ba 31 01 0c 48 d2 f2 88 22 9c 91 7d |L.5..1..H..."..}| -00000160 e3 74 f9 b3 52 bf 0e 0b e1 31 7c 2c cb fd f2 8c |.t..R....1|,....| -00000170 bf 27 40 6d 26 b7 62 47 56 91 22 00 67 9a df 4f |.'@m&.bGV.".g..O| -00000180 f0 47 57 3c a6 46 4d 16 f6 8d fc 2d 91 c4 1a bf |.GW<.FM....-....| -00000190 38 63 ec 63 fe 97 14 80 aa 5b 60 ff c8 77 57 9c |8c.c.....[`..wW.| -000001a0 d5 86 a6 76 96 b3 e9 db c9 eb dd 94 84 2a 46 f5 |...v.........*F.| -000001b0 6a c1 10 66 59 f1 13 b9 41 f3 89 26 ba 52 69 95 |j..fY...A..&.Ri.| -000001c0 b1 f3 66 30 f8 aa 90 f7 90 49 19 48 4c 25 4a 1f |..f0.....I.HL%J.| -000001d0 12 9d 67 32 79 bb 53 d8 c5 d1 b4 6e 89 75 49 c0 |..g2y.S....n.uI.| -000001e0 65 86 ac 72 23 2f 97 d3 ae e2 64 79 5e e2 10 4e |e..r#/....dy^..N| -000001f0 55 0c c6 70 d3 2e 4a 6c b0 73 0a 11 eb ae f7 a1 |U..p..Jl.s......| -00000200 a1 f0 5f 67 45 46 d3 8c 11 ff 21 62 7d ed f9 0e |.._gEF....!b}...| -00000210 2a ba b3 82 f5 6b c1 4a 4e cc 11 90 48 81 96 7a |*....k.JN...H..z| -00000220 df f9 22 ae 53 31 14 9d c9 5c 85 e7 db a2 dd 02 |..".S1...\......| -00000230 56 eb d0 fe 20 35 21 c9 33 63 b5 b7 a8 93 30 7f |V... 5!.3c....0.| -00000240 86 1f d1 af b1 ff 3e 9a d1 a8 90 d9 9c 86 55 e8 |......>.......U.| -00000250 d0 4c c4 6d a3 ce c6 c0 df f8 a8 b6 43 03 ae fc |.L.m........C...| -00000260 7d 94 7b fe be 85 46 d8 42 9d b6 15 b9 a3 27 3d |}.{...F.B.....'=| -00000270 80 64 54 c8 53 c4 a7 94 52 8f 9d 4c 58 54 a5 c4 |.dT.S...R..LXT..| -00000280 e0 e7 2e cb f3 8c d0 82 3f 95 76 c9 ea ea 80 41 |........?.v....A| -00000290 21 5d 3e a3 1e be 4e 0b ce 10 ab 61 a5 76 ef 62 |!]>...N....a.v.b| -000002a0 50 1b 52 a8 75 23 fd eb ea 76 f9 d8 41 3c a2 e4 |P.R.u#...v..A<..| -000002b0 21 cb 56 f7 40 81 78 56 22 06 2a 38 fc 1f d8 9f |!.V.@.xV".*8....| -000002c0 38 b0 7a 93 f0 8c ad 3e 54 27 a2 d7 8b 2c 79 46 |8.z....>T'...,yF| -000002d0 15 65 f1 55 b2 2a 06 a1 97 9b 47 23 f8 9a 3f 88 |.e.U.*....G#..?.| -000002e0 8e 26 7e 13 cd 6e 8b cb d5 a5 78 48 f7 ba ad d8 |.&~..n....xH....| -000002f0 08 3b 34 5b 52 cd e3 2d 12 ac 81 00 c0 d0 4d df |.;4[R..-......M.| -00000300 56 d6 40 86 91 31 3d ba 6b 41 bc 51 6f ac b2 df |V.@..1=.kA.Qo...| -00000310 90 4b 78 17 03 03 00 99 21 0f 5b 18 54 84 98 0c |.Kx.....!.[.T...| -00000320 3a 7b 0b db 99 0e 09 f6 b7 4f a9 cc da bf 4c ac |:{.......O....L.| -00000330 5f 44 fc ba 9d 5d 52 d5 ec 2e 08 0c cc 3c e1 72 |_D...]R......<.r| -00000340 10 77 5b 7b 55 f7 c1 44 a3 25 e0 48 20 9a 3a de |.w[{U..D.%.H .:.| -00000350 2f ae 30 a9 e9 5b 75 84 e3 59 f0 6b 23 a6 d8 20 |/.0..[u..Y.k#.. | -00000360 16 51 2a 19 61 60 35 28 74 41 32 fa 97 8d 3b ed |.Q*.a`5(tA2...;.| -00000370 ff 64 94 d7 27 4c 9b 1e 5e b8 89 43 e3 ae 2a b6 |.d..'L..^..C..*.| -00000380 60 a8 bb f0 d1 75 85 15 bb 95 3c 82 f1 62 da b1 |`....u....<..b..| -00000390 25 d2 58 7d 67 7f 02 5b b4 91 68 3c 70 10 09 94 |%.X}g..[..h...-2.| +000003c0 cd 16 ab da cd e7 93 0d c2 90 a2 62 7b 3c 54 bb |...........b{>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 c9 09 ac f5 44 |..........5....D| -00000010 40 83 88 5a b9 46 70 b9 ff 9b 2e bb b4 7e 72 b0 |@..Z.Fp......~r.| -00000020 85 26 d6 37 33 ec d1 ac ce f4 db 72 8c e1 07 b5 |.&.73......r....| -00000030 d0 ce ee 2f 19 77 62 ec 97 ae 1b e1 5f 85 bf c4 |.../.wb....._...| -00000040 17 03 03 00 17 1c ae 0f 1d 50 be 4b d0 64 4f 23 |.........P.K.dO#| -00000050 41 60 d9 c7 f5 60 a6 5c 38 14 fd d5 |A`...`.\8...| +00000000 14 03 03 00 01 01 17 03 03 00 35 a8 d6 93 8f 7e |..........5....~| +00000010 65 3a ee 6f c8 37 2a 27 14 dc b7 19 0e aa 14 b6 |e:.o.7*'........| +00000020 22 21 2d ea f4 00 d1 60 55 c0 f1 56 db 43 7a f0 |"!-....`U..V.Cz.| +00000030 1a 47 ce 93 d9 07 7e 61 43 92 3a 95 a9 54 7b c6 |.G....~aC.:..T{.| +00000040 17 03 03 00 17 e6 e4 52 74 15 e2 18 d7 14 59 29 |.......Rt.....Y)| +00000050 59 d8 ce 49 68 3a a8 79 9e f4 ee f1 |Y..Ih:.y....| >>> Flow 4 (server to client) -00000000 17 03 03 00 16 ad 61 13 66 9c 3c dd 88 42 2c 6c |......a.f.<..B,l| -00000010 d1 22 5d b4 b2 6f f0 68 4f 37 4d |."]..o.hO7M| +00000000 17 03 03 00 16 e6 cd 54 e3 31 d9 70 20 25 f4 aa |.......T.1.p %..| +00000010 cd 8f fe e7 88 6b 7f 62 9b 7b de |.....k.b.{.| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 e5 b5 ff ad d4 f5 e5 55 04 83 a7 |............U...| -00000010 59 43 9a 3e 68 4d 38 6f b1 1c 30 |YC.>hM8o..0| +00000000 17 03 03 00 16 bd e9 c4 24 4a 6d 76 aa 83 bb da |........$Jmv....| +00000010 ec 9e d0 c9 38 cc 6b 3c 65 38 91 |....8.k>> Flow 6 (server to client) -00000000 17 03 03 00 1a 64 0c f4 8e 8f 2b 04 e2 36 28 77 |.....d....+..6(w| -00000010 a2 28 97 4b 15 ba 1b b2 10 31 b3 4d 87 09 af |.(.K.....1.M...| +00000000 17 03 03 00 1a 6a e1 ea df 76 a9 fc 4a 80 7b 49 |.....j...v..J.{I| +00000010 dd fa c3 87 e9 e7 c9 b3 ab bf bc a7 d8 cd 36 |..............6| >>> Flow 7 (client to server) -00000000 17 03 03 00 1d 90 c9 33 bf fc 76 12 3d af 9e c8 |.......3..v.=...| -00000010 8c ca e7 a1 63 6e 80 91 b1 7f 5e e4 dc c2 e6 1c |....cn....^.....| -00000020 b6 2b 17 03 03 00 13 ef a8 30 91 b1 20 fe 82 79 |.+.......0.. ..y| -00000030 44 31 a8 af 99 bb 5e 97 75 a3 |D1....^.u.| +00000000 17 03 03 00 1d 1e c5 6f 93 48 41 07 03 e5 8c 6f |.......o.HA....o| +00000010 09 8e 2f 8e da cb 6e 01 e9 b8 6e f6 3f 59 5c 17 |../...n...n.?Y\.| +00000020 91 46 17 03 03 00 13 35 33 12 5e d3 97 0a 1c 54 |.F.....53.^....T| +00000030 cf 54 bb 7d 78 2e 57 a2 5b 39 |.T.}x.W.[9| diff --git a/crypto/tls/testdata/Client-TLSv13-P256-ECDHE b/crypto/tls/testdata/Client-TLSv13-P256-ECDHE index fa8d312384f..410f0dd189a 100644 --- a/crypto/tls/testdata/Client-TLSv13-P256-ECDHE +++ b/crypto/tls/testdata/Client-TLSv13-P256-ECDHE @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 01 19 01 00 01 15 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 33 01 00 01 2f 03 03 00 00 00 00 00 |....3.../.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,88 +7,90 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 9a 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| +00000080 01 00 00 b4 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| -000000a0 00 0a 00 04 00 02 00 17 00 0d 00 1a 00 18 08 04 |................| +000000a0 00 0a 00 04 00 02 00 17 00 0d 00 16 00 14 08 04 |................| 000000b0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| -000000c0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| -000000d0 02 03 01 00 33 00 47 00 45 00 17 00 41 04 1e 18 |....3.G.E...A...| -000000e0 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f |7...Q.5uq..T[...| -000000f0 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b |.g..$ >.V...(^.+| -00000100 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 |-O....lK[.V.2B.X| -00000110 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |..I..h.A.Vk.Z.| +000000c0 06 03 00 32 00 1a 00 18 08 04 04 03 08 07 08 05 |...2............| +000000d0 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 |................| +000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| +000000f0 47 00 45 00 17 00 41 04 1e 18 37 ef 0d 19 51 88 |G.E...A...7...Q.| +00000100 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ | +00000110 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....| +00000120 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h| +00000130 1a 41 03 56 6b dc 5a 89 |.A.Vk.Z.| >>> Flow 2 (server to client) -00000000 16 03 03 00 9b 02 00 00 97 03 03 1c 1a ee 30 2f |..............0/| -00000010 02 10 0c 84 ee 6a 2c d1 67 76 00 8a 16 e5 15 c5 |.....j,.gv......| -00000020 4c d7 a9 26 33 43 9a 9a d6 f8 e7 20 00 00 00 00 |L..&3C..... ....| +00000000 16 03 03 00 9b 02 00 00 97 03 03 1f 9f 7f 3f 27 |..............?'| +00000010 c5 5c f2 f1 bb cc a2 89 0d 7f 66 6a ff 85 7e 55 |.\........fj..~U| +00000020 ec 47 a6 5e 9c 09 00 ec 96 e2 a7 20 00 00 00 00 |.G.^....... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| -00000060 f0 2e aa 75 ea 32 f4 3c ea b7 61 13 0f 22 8d 39 |...u.2.<..a..".9| -00000070 9e 0a 53 c8 d6 92 ea 5e 87 5b 46 d3 71 2d d1 df |..S....^.[F.q-..| -00000080 fa 1e 9a 6a 0e b2 bc d7 91 6e 26 56 17 24 11 d8 |...j.....n&V.$..| -00000090 0f be c0 1d f5 fd c7 9d 2d 3c a0 0f ee 03 70 1f |........-<....p.| -000000a0 14 03 03 00 01 01 17 03 03 00 17 8e 76 66 0d 44 |............vf.D| -000000b0 aa a2 d9 80 84 7c 6d 42 f0 ee 9f a3 6c b8 83 21 |.....|mB....l..!| -000000c0 5d 7b 17 03 03 02 6d 18 d3 53 cc 09 6a 23 fc c5 |]{....m..S..j#..| -000000d0 a9 2e 73 b4 3d ea 54 56 42 f5 1f 71 3e 8f 8e 7b |..s.=.TVB..q>..{| -000000e0 12 18 d7 d6 ab ed 24 5f 16 c8 18 5e e0 28 84 40 |......$_...^.(.@| -000000f0 89 49 a7 91 57 d6 2b a0 9c ab 5d 85 ac 4f 6b 70 |.I..W.+...]..Okp| -00000100 c3 31 e0 57 87 d7 7c 45 27 34 54 eb 85 02 14 2c |.1.W..|E'4T....,| -00000110 a0 53 4f ec 21 9f 04 91 38 b8 df 2c 5d 0b 79 0a |.SO.!...8..,].y.| -00000120 4f 96 79 15 72 de b5 fb 43 1f d8 71 62 d8 e0 69 |O.y.r...C..qb..i| -00000130 21 13 87 ab e5 b8 e5 86 01 74 25 b7 39 fc 86 e2 |!........t%.9...| -00000140 2f de 0b 1f 8c db b2 98 b3 47 c1 4e dd db 36 d3 |/........G.N..6.| -00000150 28 de cf 4c 4d 54 8e a3 e5 d3 38 19 1f 4b 05 7f |(..LMT....8..K..| -00000160 9a e1 59 4c a3 4e 42 b6 71 0d 9c 96 e4 d8 29 73 |..YL.NB.q.....)s| -00000170 4e e6 f5 87 56 04 99 c2 56 15 6c 8b 04 7c e5 83 |N...V...V.l..|..| -00000180 8b f3 42 e8 97 7a b0 cc 7d 15 b8 84 d3 08 dd c1 |..B..z..}.......| -00000190 89 f5 d4 19 d2 f6 fd 32 b4 37 6e 6a cc 0c 7a 69 |.......2.7nj..zi| -000001a0 09 57 78 36 d4 5b 8c 23 0f e6 39 08 4c 58 3e 3f |.Wx6.[.#..9.LX>?| -000001b0 b1 a0 ae 2e 85 b7 64 45 dd e1 ae c4 91 53 8c 6f |......dE.....S.o| -000001c0 02 70 45 f0 97 7b c8 90 88 0e 95 ed 1e 81 fc 86 |.pE..{..........| -000001d0 27 83 3d 32 43 d6 e4 f3 84 c6 c4 c1 b2 1c 0d 4a |'.=2C..........J| -000001e0 22 78 cd 1c f8 0a aa 19 1a 96 cc 46 6d a0 7f c7 |"x.........Fm...| -000001f0 2f d8 68 de 48 7d ae 42 b3 75 2a d5 ab cf e7 a7 |/.h.H}.B.u*.....| -00000200 a1 e6 66 e0 88 d8 14 25 81 21 4a 6f f7 7c 84 57 |..f....%.!Jo.|.W| -00000210 9c cd 45 8a c0 2d 5f 97 b6 66 96 f1 be d8 02 d2 |..E..-_..f......| -00000220 a4 8e fb 0d c4 cc 02 12 1d b7 76 73 8d 73 8e 71 |..........vs.s.q| -00000230 ec 62 4b ba d1 94 98 e5 de 45 f4 92 22 79 9a 2e |.bK......E.."y..| -00000240 b4 12 a6 f8 ab 8a 52 c3 df f8 77 a9 71 8b ff d6 |......R...w.q...| -00000250 2b bc 47 0b 63 5b 0f cf f8 f1 86 7a 72 91 78 7b |+.G.c[.....zr.x{| -00000260 b8 52 74 96 40 4c 08 f3 ca 46 ef d9 b9 6d 7a dc |.Rt.@L...F...mz.| -00000270 2c da f1 c2 c4 1f 19 38 84 cf 7d b7 5d f2 19 a7 |,......8..}.]...| -00000280 bc 81 70 48 1c 5d da e7 e1 8f 94 33 fa b9 44 97 |..pH.].....3..D.| -00000290 52 7a 22 75 f3 3e 08 f5 d3 66 be 63 8e e6 fc 7b |Rz"u.>...f.c...{| -000002a0 54 6d 14 2e 88 09 c7 a1 a6 b7 8e f3 9f 66 dd a4 |Tm...........f..| -000002b0 ec 81 e9 4b 44 69 29 78 95 dd 44 80 f5 f9 41 23 |...KDi)x..D...A#| -000002c0 97 53 71 63 2d cc d0 47 d6 f7 3f 6b 61 5f 44 33 |.Sqc-..G..?ka_D3| -000002d0 61 d1 35 94 42 7b 88 b9 af 6f e2 c1 71 7b d9 12 |a.5.B{...o..q{..| -000002e0 2c b6 57 fa 42 98 27 6d 8a da f8 dd de 6f b2 ea |,.W.B.'m.....o..| -000002f0 c8 de 5c 09 cd 47 36 10 0f 52 72 39 b2 e5 92 19 |..\..G6..Rr9....| -00000300 81 2a e0 ae aa cc b5 d1 68 98 c4 69 02 fc 86 1a |.*......h..i....| -00000310 79 9c 11 54 fc 43 8a ed 63 50 83 49 ac bf 4c ad |y..T.C..cP.I..L.| -00000320 80 04 98 fd 33 19 76 49 8f fe 5a 0f 22 69 3e eb |....3.vI..Z."i>.| -00000330 d8 eb 51 71 17 03 03 00 99 42 4d 4b db 37 6c c3 |..Qq.....BMK.7l.| -00000340 fb 93 1f a6 7a 86 3c 5e 88 e5 75 d4 a1 73 4a b3 |....z.<^..u..sJ.| -00000350 0b 99 f1 a6 98 5f 6d 0f 00 0e 4f fa a3 5e 7d f0 |....._m...O..^}.| -00000360 41 dd dd 5c 71 3b 10 f9 75 07 d5 6c f2 83 83 5c |A..\q;..u..l...\| -00000370 60 32 d9 d2 b3 13 1b 6c 84 2b 02 58 da b6 18 4e |`2.....l.+.X...N| -00000380 ea 7d b3 46 2b a9 ec e7 65 3a 8e 2f 77 48 92 72 |.}.F+...e:./wH.r| -00000390 6a 82 47 bd 82 2b f7 01 6b c4 22 e2 43 78 78 03 |j.G..+..k.".Cxx.| -000003a0 3c 40 d9 6c d1 b3 5e 21 4d 52 74 e4 07 70 56 21 |<@.l..^!MRt..pV!| -000003b0 05 37 37 82 13 cd e6 ce 3f 93 61 74 b4 9a 42 7d |.77.....?.at..B}| -000003c0 26 fa 15 4f ed b7 63 22 3c 92 f3 72 9c d2 80 17 |&..O..c"<..r....| -000003d0 30 f0 17 03 03 00 35 8c f6 08 33 76 5a a4 7b ef |0.....5...3vZ.{.| -000003e0 0d 91 b6 bf fa 9e 39 19 6f 79 77 4c 4d 74 95 71 |......9.oywLMt.q| -000003f0 00 73 37 17 50 ef 55 fb 71 04 36 87 2e 16 5e 25 |.s7.P.U.q.6...^%| -00000400 9b d4 9c 52 f9 ec c5 26 7e 58 ed 9f |...R...&~X..| +00000060 f0 c5 09 c6 22 3f 23 06 65 c7 e2 1c f8 e7 c2 59 |...."?#.e......Y| +00000070 a9 9f 00 3d 1a 48 fb b5 7f e4 ad 3d 4f 2d 91 d8 |...=.H.....=O-..| +00000080 f4 2f d5 31 5c dc 2b 53 63 2b 25 1b 60 47 31 3a |./.1\.+Sc+%.`G1:| +00000090 30 72 d8 5d a4 60 9d 68 51 48 45 69 32 73 58 a5 |0r.].`.hQHEi2sX.| +000000a0 14 03 03 00 01 01 17 03 03 00 17 e9 38 fa fe 25 |............8..%| +000000b0 89 ba 85 3b 0e 66 1e 3f b9 52 55 20 e0 3c 07 6f |...;.f.?.RU .<.o| +000000c0 2c 2f 17 03 03 02 6d cf 73 3f de 91 5b 86 ff 90 |,/....m.s?..[...| +000000d0 ca a3 c9 ba e2 9e 56 53 fc 72 28 e5 98 1f 08 ca |......VS.r(.....| +000000e0 6d 0e 80 96 d2 45 74 33 3b 45 ee 2b ab 12 94 57 |m....Et3;E.+...W| +000000f0 be 00 7e f6 14 93 64 62 7b 0d 81 0e 79 8b 63 49 |..~...db{...y.cI| +00000100 36 8a 67 5c bb 33 72 fa 73 0d e1 ab 66 58 fa a3 |6.g\.3r.s...fX..| +00000110 dd 66 c2 bb 0e 64 82 39 59 e1 a0 e1 5c 84 b1 b6 |.f...d.9Y...\...| +00000120 0d 60 94 f2 ff 94 39 72 62 45 cd f6 d8 f3 33 b5 |.`....9rbE....3.| +00000130 20 99 29 c8 d5 ba 8c 49 cb 29 54 e9 cf 7e 26 1f | .)....I.)T..~&.| +00000140 25 96 41 93 82 4c 38 15 0d 0c 6d 7f 89 51 7f 43 |%.A..L8...m..Q.C| +00000150 9d 04 3a 1a 58 86 97 4e 0c 29 c0 2e f0 e7 78 42 |..:.X..N.)....xB| +00000160 f0 b4 11 cb 50 ec 45 62 c5 0a 42 11 cc aa c4 d4 |....P.Eb..B.....| +00000170 33 15 ee 43 e1 80 6f 46 16 ea 30 27 09 d1 34 e6 |3..C..oF..0'..4.| +00000180 59 f7 b0 e0 6f ea 51 bd 02 79 17 06 3f 84 75 08 |Y...o.Q..y..?.u.| +00000190 63 91 b3 58 d3 1c 61 47 bf d9 2a 9e 11 75 b2 5e |c..X..aG..*..u.^| +000001a0 7e 09 62 f2 3c ba 63 4b 2b 09 c4 90 b5 78 9a c4 |~.b.<.cK+....x..| +000001b0 be 35 9b 7f e3 11 5a 82 d8 50 b3 67 20 7a 53 ec |.5....Z..P.g zS.| +000001c0 cb f9 1a b3 b3 b6 b6 39 1b f1 fe 7a 28 27 9c ed |.......9...z('..| +000001d0 25 35 f4 f1 21 11 eb 33 61 64 1d 54 eb ef c3 d0 |%5..!..3ad.T....| +000001e0 2c 0d 76 0d 7e 90 3f 8d a4 d0 b5 d9 27 49 c7 fc |,.v.~.?.....'I..| +000001f0 cc 59 8c c5 af 59 fc 09 98 63 9c fb 63 d8 09 6f |.Y...Y...c..c..o| +00000200 55 2d 1f d2 c7 83 5f 3d ae 00 ef ca 27 03 9d b9 |U-...._=....'...| +00000210 00 03 c5 c7 e5 2d 91 47 b0 6c 67 2a 09 3e bc 57 |.....-.G.lg*.>.W| +00000220 a3 02 3f cf b2 88 d8 3d 25 c5 e1 0e 2b a2 b7 5f |..?....=%...+.._| +00000230 57 18 5c eb 8e ae 5f d6 5f 11 1b 5c 48 3b f5 84 |W.\..._._..\H;..| +00000240 b0 6e 29 3e 58 71 36 6e 66 6e e0 d0 98 b0 1b 84 |.n)>Xq6nfn......| +00000250 ca 8c 53 83 86 ca 26 7a 15 6b 6a 7c 61 91 55 45 |..S...&z.kj|a.UE| +00000260 58 cb bd b2 df df 78 22 83 36 8e 4f b6 40 70 ea |X.....x".6.O.@p.| +00000270 d1 72 33 7d 85 00 01 48 f1 75 73 db b3 aa 1d da |.r3}...H.us.....| +00000280 78 c9 e3 37 7c 1c 52 74 62 6c f6 eb af af 0b 2d |x..7|.Rtbl.....-| +00000290 ef d4 85 3d 9f 48 de 5c 4a 6e 24 69 b9 7b 87 e7 |...=.H.\Jn$i.{..| +000002a0 62 3c 26 67 8a 52 b2 73 66 90 56 07 6f ec 14 62 |b<&g.R.sf.V.o..b| +000002b0 88 15 20 e6 27 59 d4 cf 0e f0 59 cd cb 8e bd e5 |.. .'Y....Y.....| +000002c0 ca 10 39 40 54 a5 57 4e 99 70 93 b4 86 60 5f f1 |..9@T.WN.p...`_.| +000002d0 70 f5 d7 21 ef f2 11 b2 da 7a 7f 27 a8 6b fe 7f |p..!.....z.'.k..| +000002e0 e4 eb 35 9c d5 24 ef 70 4b 3c ed bd 9b b9 b9 f3 |..5..$.pK<......| +000002f0 50 a4 61 7f 24 d0 8c 7f 4f 48 09 4f 1e 26 fb 46 |P.a.$...OH.O.&.F| +00000300 ec c2 84 12 a5 6a 5f 19 f0 03 cc 50 cc 07 26 23 |.....j_....P..&#| +00000310 58 6e 68 d8 20 ae eb db 2f be a6 7b a8 ed 86 20 |Xnh. .../..{... | +00000320 61 07 03 47 e5 19 9b a7 0d 27 e0 56 9f 2a d5 19 |a..G.....'.V.*..| +00000330 e7 b3 39 07 17 03 03 00 99 3a 9b b2 61 6a 40 3a |..9......:..aj@:| +00000340 46 a8 0b 50 e3 95 d2 80 5f 5a 08 c3 54 2e 47 ac |F..P...._Z..T.G.| +00000350 f1 83 07 13 21 7f 5e 4e 1b 67 66 cc 38 a7 f3 91 |....!.^N.gf.8...| +00000360 f0 5f ac 9a 39 55 de bf 02 30 2a 87 35 85 f8 1d |._..9U...0*.5...| +00000370 32 3a 8c f8 90 6a 22 21 b2 e8 87 5e 54 6a 45 de |2:...j"!...^TjE.| +00000380 74 ff 6d 37 00 92 07 6c 09 13 c1 5e 68 bc 28 80 |t.m7...l...^h.(.| +00000390 d6 24 e5 32 fc 13 ee 68 68 91 9a e6 15 74 21 7d |.$.2...hh....t!}| +000003a0 2d b2 c8 f5 1d 05 69 5c 80 ee 8b 7c 3e 23 be 35 |-.....i\...|>#.5| +000003b0 d4 54 3c 52 66 2a f1 12 98 5d 3a 3f 44 26 84 d8 |.T>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 f5 7f 27 09 c2 |..........5..'..| -00000010 54 9d e7 a7 3b 14 b3 f2 a6 6d 27 5f 9b 79 04 17 |T...;....m'_.y..| -00000020 28 5c de 4f 67 cf a5 24 e4 d3 c5 e1 38 fa 7e e8 |(\.Og..$....8.~.| -00000030 97 03 7e 66 3b d0 6b e7 f8 7e 97 e0 db 6a da 79 |..~f;.k..~...j.y| -00000040 17 03 03 00 17 30 1a e2 fe 4a 7a 03 03 82 f6 05 |.....0...Jz.....| -00000050 e8 18 67 1d 14 ab 4f 3c 22 c6 45 f5 17 03 03 00 |..g...O<".E.....| -00000060 13 f8 8f 43 e7 74 3c a0 28 b2 71 5a 85 69 e5 86 |...C.t<.(.qZ.i..| -00000070 06 e3 4c 91 |..L.| +00000000 14 03 03 00 01 01 17 03 03 00 35 70 3d 2c 7e 6a |..........5p=,~j| +00000010 d9 c5 58 7b 1d b5 d8 af 9e ca b8 30 2a 9b c3 c8 |..X{.......0*...| +00000020 fa 1c 76 f0 64 f8 4c 01 24 19 18 b2 2e 70 b9 e1 |..v.d.L.$....p..| +00000030 d3 45 96 e7 08 7e 7b c8 7d 1a c8 b7 87 13 9d 1d |.E...~{.}.......| +00000040 17 03 03 00 17 3f 62 68 a3 27 6c c3 12 33 ed e6 |.....?bh.'l..3..| +00000050 0e 87 e6 c4 3e 63 55 2a 15 11 aa 35 17 03 03 00 |....>cU*...5....| +00000060 13 f8 81 0f 72 73 8b d0 14 af fe f2 9d b7 c7 fd |....rs..........| +00000070 16 17 b9 60 |...`| diff --git a/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE b/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE index 855f63de210..9e53626d5dc 100644 --- a/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE +++ b/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE @@ -1,5 +1,5 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 f8 01 00 00 f4 03 03 00 00 00 00 00 |................| +00000000 16 03 01 01 12 01 00 01 0e 03 03 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -7,84 +7,86 @@ 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| -00000080 01 00 00 79 00 0b 00 02 01 00 ff 01 00 01 00 00 |...y............| +00000080 01 00 00 93 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| -000000a0 00 0a 00 04 00 02 00 1d 00 0d 00 1a 00 18 08 04 |................| +000000a0 00 0a 00 04 00 02 00 1d 00 0d 00 16 00 14 08 04 |................| 000000b0 04 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 |................| -000000c0 06 03 02 01 02 03 00 2b 00 09 08 03 04 03 03 03 |.......+........| -000000d0 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d |....3.&.$... /.}| -000000e0 a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 |.G.bC.(.._.).0..| -000000f0 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |........_X.;t| +000000c0 06 03 00 32 00 1a 00 18 08 04 04 03 08 07 08 05 |...2............| +000000d0 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 |................| +000000e0 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 33 00 |.+............3.| +000000f0 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 |&.$... /.}.G.bC.| +00000100 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +00000110 90 99 5f 58 cb 3b 74 |.._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 6c f6 24 8a 4a |....z...v..l.$.J| -00000010 82 87 8f c9 9a a3 5a d2 4a 24 d3 52 c8 5d 52 95 |......Z.J$.R.]R.| -00000020 0f 12 e8 8e e6 0c a6 5d 60 de 3c 20 00 00 00 00 |.......]`.< ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 5a 42 7b 30 69 |....z...v..ZB{0i| +00000010 87 6c 87 6a 9c c4 4f 41 b5 18 58 d5 7a 1d 7d da |.l.j..OA..X.z.}.| +00000020 92 29 4c dd 57 6b 4d 0c f9 7c 74 20 00 00 00 00 |.)L.WkM..|t ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 1b |..+.....3.$... .| -00000060 e6 5f 3d 83 17 1c a6 90 45 f9 00 d9 96 be 4a 58 |._=.....E.....JX| -00000070 ec 82 73 4d e6 8c 74 e9 80 bc 3a 48 1b 93 71 14 |..sM..t...:H..q.| -00000080 03 03 00 01 01 17 03 03 00 17 71 c1 fc 68 5e 33 |..........q..h^3| -00000090 54 8f 43 df 20 55 ac 3b e8 a4 ee 68 ff 88 7c 71 |T.C. U.;...h..|q| -000000a0 92 17 03 03 02 6d 2a 26 5c 45 13 5f 75 46 56 41 |.....m*&\E._uFVA| -000000b0 25 92 a1 6f cd 7b 01 e2 cb 76 81 4d 33 f0 9d d1 |%..o.{...v.M3...| -000000c0 0d db b1 90 1a a7 d9 a8 4a 79 b1 12 59 62 0d c8 |........Jy..Yb..| -000000d0 cc 92 16 26 27 3e 07 b6 8a 15 77 a8 f6 c3 02 e7 |...&'>....w.....| -000000e0 44 0d b5 d3 11 57 6b 81 15 7d 23 b3 91 82 21 3c |D....Wk..}#...!<| -000000f0 0a 0c ef d5 5b 96 5d 85 aa 3a 1e a6 7b fc 3a eb |....[.]..:..{.:.| -00000100 24 af 13 fa 7f 90 0a 83 b5 0a 0b d0 f7 0c 2d 99 |$.............-.| -00000110 75 9b 84 0c d8 dc 60 a3 62 ed 64 55 02 73 a1 74 |u.....`.b.dU.s.t| -00000120 c1 53 c6 97 a5 23 7c 19 c8 f7 1c 97 e9 e9 f8 ee |.S...#|.........| -00000130 4c 47 7e c4 5e 0f 03 fc 60 9e ba 47 ea a9 9b ef |LG~.^...`..G....| -00000140 9a 04 62 e3 db bf 30 d7 5a 1f 20 c9 4c 37 ff 0e |..b...0.Z. .L7..| -00000150 46 d9 ce 85 c5 47 16 43 9a 89 0b 97 44 7a be 09 |F....G.C....Dz..| -00000160 5d 03 a0 b1 1f a6 ca 78 0d fb f4 1a 6d 3a ec 40 |]......x....m:.@| -00000170 1e 58 fc 67 5e bb 69 a1 ae 1d 6d bc b4 80 b9 71 |.X.g^.i...m....q| -00000180 1a 11 12 35 6a 2a 0c dc b3 b5 4b 0a 06 a7 8b be |...5j*....K.....| -00000190 38 4b 70 32 d4 51 e3 99 5b 60 28 e7 9a 60 90 6b |8Kp2.Q..[`(..`.k| -000001a0 1f 3a 9b 4b 66 fd e6 76 b5 8c 29 c3 36 ae a8 81 |.:.Kf..v..).6...| -000001b0 7e 7c bf e7 46 7d 13 27 0d 38 75 f0 15 e1 64 93 |~|..F}.'.8u...d.| -000001c0 1e 26 bc a8 5d 95 60 a2 e5 42 7f 2f 08 a1 e8 d3 |.&..].`..B./....| -000001d0 79 e8 5e 1f 02 45 cc 05 ca 63 7b f2 d9 ad af ab |y.^..E...c{.....| -000001e0 5a 94 f0 16 e7 60 14 c2 3d 05 3f 8d bb 33 c1 ca |Z....`..=.?..3..| -000001f0 79 28 04 c7 20 07 c8 13 89 7a 11 a2 54 6d b8 d5 |y(.. ....z..Tm..| -00000200 e1 b7 b1 43 48 9b a9 b9 e8 e0 40 7e 5a 36 24 70 |...CH.....@~Z6$p| -00000210 42 9a 51 70 6e 22 8a 2b 4b 9d b0 58 ff ae a9 45 |B.Qpn".+K..X...E| -00000220 34 b2 8b c1 35 d8 65 a5 7e 1f 32 fd 51 21 79 00 |4...5.e.~.2.Q!y.| -00000230 79 20 f7 5f 8a e2 e0 b3 4a 78 3b 03 a8 03 b6 ef |y ._....Jx;.....| -00000240 b2 25 37 e9 f3 ce 22 f0 2b fc f8 dd be 50 10 22 |.%7...".+....P."| -00000250 0b fa fb 04 ab a7 33 07 48 2f ca ec 0d fe 19 75 |......3.H/.....u| -00000260 cc c5 3d 17 36 06 5c 07 08 15 df 36 6c 4f f4 73 |..=.6.\....6lO.s| -00000270 50 49 ff 47 ba 47 6d e1 bb 2d 8f 77 d5 44 a9 87 |PI.G.Gm..-.w.D..| -00000280 2a 05 12 52 bf 2b e2 4b 64 94 9c 89 bb 2c 65 cb |*..R.+.Kd....,e.| -00000290 59 2a f0 1a 15 b2 e3 6e 5a cc 48 b4 44 6c 44 07 |Y*.....nZ.H.DlD.| -000002a0 80 01 93 25 86 83 f2 8f 01 e6 ef 5e 9a 36 4e 7f |...%.......^.6N.| -000002b0 bc 27 0e 4d f0 67 3a de 29 b5 e9 6a 7f 4b b4 77 |.'.M.g:.)..j.K.w| -000002c0 9b e2 3b 73 c9 51 e5 a6 df 97 a7 02 fa f2 f7 db |..;s.Q..........| -000002d0 df 71 fb d1 ad 64 37 46 3e de 57 de 1d fc 8f 6e |.q...d7F>.W....n| -000002e0 bb 6f 58 3f 87 00 d1 a3 52 a5 35 12 17 83 19 a4 |.oX?....R.5.....| -000002f0 2b be 31 bd dc a6 62 ca c3 09 39 e1 cd 0b 64 44 |+.1...b...9...dD| -00000300 1a ef 65 26 f3 e5 31 fb 61 56 df d3 11 d9 cc 65 |..e&..1.aV.....e| -00000310 7f 8f ab 17 03 03 00 99 94 ce 37 3c e1 7f b1 f5 |..........7<....| -00000320 7e 2b 04 17 45 3d 38 40 1b 82 0e f7 22 ef 28 ce |~+..E=8@....".(.| -00000330 1a 69 33 a6 ad c6 1f ab 08 12 31 b4 c7 41 ac c5 |.i3.......1..A..| -00000340 b3 e5 4b 84 56 d9 0c 53 58 4c 8f 40 3a 34 66 d0 |..K.V..SXL.@:4f.| -00000350 c7 8f 9b b3 26 25 1f 68 fc 97 ba a7 de ac cf c5 |....&%.h........| -00000360 8b b3 26 99 68 6e ca e9 65 47 07 bd 38 15 f3 0c |..&.hn..eG..8...| -00000370 d0 14 8e 6d 89 a2 ad cd ad ef 00 54 07 5a 4b ef |...m.......T.ZK.| -00000380 02 ce b9 a1 b0 d0 d6 f7 bb e0 91 51 72 87 99 50 |...........Qr..P| -00000390 f4 68 4c 0e d8 fa 00 d4 dd bd 1d 2e 7b f6 e2 61 |.hL.........{..a| -000003a0 d3 a8 46 9c f7 dc 2a 04 be 3c 42 85 4f ad 59 20 |..F...*..'.........| +000000f0 14 3c a1 5b 2e 60 55 34 73 f2 1d c2 24 df 09 55 |.<.[.`U4s...$..U| +00000100 e5 5b b6 43 de d7 48 6b cd 15 da 06 f1 b6 56 0b |.[.C..Hk......V.| +00000110 fb 7e 97 f4 40 2f 6b c9 5b 4d 0c 70 8d d5 1c 21 |.~..@/k.[M.p...!| +00000120 d6 a2 4f ab e9 c7 cb 69 0e d0 86 d0 b8 1e c5 6b |..O....i.......k| +00000130 3d 2f 78 f7 ab fd db 06 5c 59 69 fe 74 69 2f c9 |=/x.....\Yi.ti/.| +00000140 a0 36 e2 08 2e 42 23 05 da 89 33 e7 b5 c3 b2 5a |.6...B#...3....Z| +00000150 d4 7e 4c 99 1c 24 a8 62 9b 92 7d bb c0 e1 4a 90 |.~L..$.b..}...J.| +00000160 72 83 4d b2 74 13 45 3f ef 91 7c b0 c4 6b 4e f5 |r.M.t.E?..|..kN.| +00000170 5c 3d 56 6f fe 96 63 c2 fe 2c 88 23 ab 92 08 bf |\=Vo..c..,.#....| +00000180 c5 08 25 81 a5 49 a6 5c 95 da 09 b2 c9 4b e0 f2 |..%..I.\.....K..| +00000190 59 4e 5a 67 6b 71 c7 ba 69 ff a8 f5 6d 21 52 68 |YNZgkq..i...m!Rh| +000001a0 05 d6 61 0e d6 67 d9 64 3d 26 a3 65 3c 55 11 42 |..a..g.d=&.e.}..E0L-rC.| +00000260 4f a3 08 d2 7f 70 e9 31 7b c8 cd 77 fc 3e 82 70 |O....p.1{..w.>.p| +00000270 48 ed 83 55 79 16 c1 8c 69 50 60 53 48 08 5b 66 |H..Uy...iP`SH.[f| +00000280 fe 78 02 06 16 ba 02 90 85 11 7b 49 36 71 58 35 |.x........{I6qX5| +00000290 46 7f fd 0f de dc 11 ae 3a bd df 79 93 f9 e3 8d |F.......:..y....| +000002a0 4c d8 c5 55 74 34 7f 01 dd 4d d5 ef ef 4e 3d d3 |L..Ut4...M...N=.| +000002b0 31 94 3f 1c 9b 6c 44 d0 3b 73 d1 5f b4 b6 48 5d |1.?..lD.;s._..H]| +000002c0 16 ba 17 0b d0 f5 b4 16 18 1f 85 be dc f1 75 71 |..............uq| +000002d0 17 f8 b0 8a f3 d2 80 24 d5 3b cd 58 f4 9b 03 e5 |.......$.;.X....| +000002e0 64 c5 ae 5e 9a 25 d2 bb a2 28 91 4b 2e 81 4d e4 |d..^.%...(.K..M.| +000002f0 4e 25 57 12 fc 7a 87 36 66 0b 76 21 66 17 a0 e5 |N%W..z.6f.v!f...| +00000300 0a f7 00 31 48 62 a9 70 f1 75 1b e0 78 c9 fa de |...1Hb.p.u..x...| +00000310 11 6f 3d 17 03 03 00 99 72 f9 ad 67 80 2a 9f 04 |.o=.....r..g.*..| +00000320 a9 0a fb 6f 03 90 88 35 7f cb 97 5f 4e a2 1e a8 |...o...5..._N...| +00000330 34 80 96 d1 60 b4 b4 12 ec c3 2b 15 c9 a0 f9 28 |4...`.....+....(| +00000340 50 1c 53 1d fc 32 a2 c7 c0 03 58 1b 83 a6 ee 94 |P.S..2....X.....| +00000350 2d 98 99 83 62 6a 52 a0 c5 42 94 4f 3a 26 2e 44 |-...bjR..B.O:&.D| +00000360 7b 03 f5 2a 0e 9e 48 e4 2a 18 2e 9b 42 7f 34 d2 |{..*..H.*...B.4.| +00000370 3c b2 92 52 cc 51 0e f0 fd c7 4d e6 d7 1b b2 44 |<..R.Q....M....D| +00000380 99 48 e7 da 1e 43 37 d1 ac 80 c5 34 21 1b d8 0c |.H...C7....4!...| +00000390 9c 92 0d b4 27 b0 78 43 06 a2 90 42 c4 99 5e 5f |....'.xC...B..^_| +000003a0 a4 36 69 a5 a1 92 12 5e 51 47 7f ff 50 07 ac 8a |.6i....^QG..P...| +000003b0 35 17 03 03 00 35 86 65 34 2f d0 12 2a 0b 7c 50 |5....5.e4/..*.|P| +000003c0 b4 c5 67 30 cc 4d cf 4f f7 be a5 0d 2c b2 96 ae |..g0.M.O....,...| +000003d0 da 70 a3 74 c2 e7 9a 18 61 17 95 da 00 ac cc 89 |.p.t....a.......| +000003e0 66 a1 e8 aa ca 8f 02 3c b5 16 3d |f......<..=| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 19 50 85 5d 08 |..........5.P.].| -00000010 c9 5e 25 05 37 ed cc 54 fe ba 86 3e 8a d4 e9 fd |.^%.7..T...>....| -00000020 66 54 6e a3 1f 8b 4f 95 cf 04 51 db 60 96 ae 78 |fTn...O...Q.`..x| -00000030 6b 7d 19 63 03 2a b6 e5 97 37 26 79 98 3f 85 52 |k}.c.*...7&y.?.R| -00000040 17 03 03 00 17 c9 80 91 3e 92 1e a7 9b 00 a3 01 |........>.......| -00000050 19 31 d0 6f 2e 69 0c 15 03 73 20 36 17 03 03 00 |.1.o.i...s 6....| -00000060 13 97 85 32 6f a2 9c 72 be ca 43 db 18 a7 98 b7 |...2o..r..C.....| -00000070 67 44 71 ce |gDq.| +00000000 14 03 03 00 01 01 17 03 03 00 35 a0 a0 1c ae a9 |..........5.....| +00000010 1a 1f 74 01 92 fe bf 91 c4 aa 8b f2 84 7e 39 c1 |..t..........~9.| +00000020 cb f4 ae a8 76 0c de 9e 54 7f ca 4a a2 d3 07 ef |....v...T..J....| +00000030 8e ed 8a be 54 ad 76 fe b6 62 24 4d a7 88 d5 7a |....T.v..b$M...z| +00000040 17 03 03 00 17 a2 d4 e7 78 ef 4a 2e 66 52 6f 2a |........x.J.fRo*| +00000050 e3 07 e0 9c fc 19 f6 f8 96 88 bb be 17 03 03 00 |................| +00000060 13 43 01 14 16 42 27 8a b9 a9 98 5f c7 06 4d 20 |.C...B'...._..M | +00000070 8b c3 cb 33 |...3| diff --git a/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES index c5d947c2ce8..3bc3a75b366 100644 --- a/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 51 01 00 00 4d 03 01 5e bf ff e7 c2 |....Q...M..^....| -00000010 c1 98 4a a3 cf 5a e8 8d 8f 19 9e 85 48 5b 92 cc |..J..Z......H[..| -00000020 7d 0c 14 1e 2e 50 5b d7 dd fe ef 00 00 04 c0 0a |}....P[.........| +00000000 16 03 01 00 51 01 00 00 4d 03 01 76 4b 58 ef 57 |....Q...M..vKX.W| +00000010 d5 8d ba b7 0b fe d4 b3 2b a7 76 7c f1 72 59 39 |........+.v|.rY9| +00000020 fa 02 66 88 4a 55 72 15 9e 42 8c 00 00 04 c0 0a |..f.JUr..B......| 00000030 00 ff 01 00 00 20 00 0b 00 04 03 00 01 02 00 0a |..... ..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 00000050 00 00 00 17 00 00 |......| @@ -43,37 +43,37 @@ 00000220 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 |.3.......7z..z..| 00000230 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 |....i..|V..1x+..| 00000240 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 |x.....N6$1{j.9..| -00000250 07 8f 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 |..*............ | +00000250 07 8f 2a 16 03 01 00 b3 0c 00 00 af 03 00 1d 20 |..*............ | 00000260 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 |/.}.G.bC.(.._.).| 00000270 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |0.........._X.;t| -00000280 00 8b 30 81 88 02 42 00 c3 eb 60 b8 d3 af cb 2d |..0...B...`....-| -00000290 4f ca 46 6d e4 fe 47 41 82 1e d4 14 0f 08 ab b6 |O.Fm..GA........| -000002a0 b8 41 8b 46 f5 28 bb 87 28 73 a0 5c e9 ce f5 56 |.A.F.(..(s.\...V| -000002b0 11 02 17 2c 39 b6 28 6c ec de 12 bf 22 91 3d 06 |...,9.(l....".=.| -000002c0 ac 8e 0a 92 b1 46 69 86 44 02 42 01 fd 70 6e 63 |.....Fi.D.B..pnc| -000002d0 1b 2a 21 47 9b 42 9c d4 4a 38 20 dd 94 05 c4 0f |.*!G.B..J8 .....| -000002e0 5d b2 48 c8 17 90 01 4d 4f 7e 7a ef bb b2 5b 26 |].H....MO~z...[&| -000002f0 7e e1 24 f5 80 93 69 72 3f cf bb 5d 52 ee ec b4 |~.$...ir?..]R...| -00000300 cc 0c 96 1f 93 4c d6 a8 c7 b2 91 f5 6d 16 03 01 |.....L......m...| -00000310 00 04 0e 00 00 00 |......| +00000280 00 89 30 81 86 02 41 00 b5 7c a4 63 77 fa 75 cd |..0...A..|.cw.u.| +00000290 82 a5 75 15 08 09 e8 6d e9 ba 07 1f f9 9c 24 a5 |..u....m......$.| +000002a0 30 08 d0 51 3b d1 82 14 14 dd 5a 5d c9 2d 91 6f |0..Q;.....Z].-.o| +000002b0 b3 92 30 f1 38 36 e8 34 9e 99 50 a0 c4 29 04 ef |..0.86.4..P..)..| +000002c0 97 f3 cd dc be 22 86 b9 02 41 6a dd 3a 57 5b 61 |....."...Aj.:W[a| +000002d0 ff 68 7d 1e 5e bb 67 5f 76 44 7c f2 f2 03 95 f2 |.h}.^.g_vD|.....| +000002e0 e0 1a 53 70 ce b0 fa cc 7a f3 9a e3 2f 37 a3 cf |..Sp....z.../7..| +000002f0 b5 ca 1d fb fe a3 0d e2 d6 c1 d2 7d 48 80 5b 82 |...........}H.[.| +00000300 56 29 1b b7 43 2e b3 38 19 39 49 16 03 01 00 04 |V)..C..8.9I.....| +00000310 0e 00 00 00 |....| >>> Flow 3 (client to server) -00000000 16 03 01 00 25 10 00 00 21 20 ec f2 2d ca 02 ce |....%...! ..-...| -00000010 11 2d eb 26 d7 d9 fc b2 a7 2d 34 5b a9 3a 0b 2f |.-.&.....-4[.:./| -00000020 5c 49 a9 69 1a 3a 83 90 ec 5f 14 03 01 00 01 01 |\I.i.:..._......| -00000030 16 03 01 00 30 9f 06 c7 a7 a0 c3 a5 3d 60 6e fb |....0.......=`n.| -00000040 c6 18 a4 d2 80 2e ad 8f cf 92 84 94 36 f8 81 28 |............6..(| -00000050 c5 3f 37 e8 d6 e7 6d a3 f5 32 63 a0 ab 7a db 12 |.?7...m..2c..z..| -00000060 17 e1 e4 33 d6 |...3.| +00000000 16 03 01 00 25 10 00 00 21 20 82 03 ad 10 45 0a |....%...! ....E.| +00000010 b9 a4 85 0d 88 bb 9e 16 f1 6c 6a 17 c0 11 09 48 |.........lj....H| +00000020 b4 8b 27 4e 3a 45 a1 b7 a2 03 14 03 01 00 01 01 |..'N:E..........| +00000030 16 03 01 00 30 33 5d a1 85 df 96 6d cf a1 b3 c4 |....03]....m....| +00000040 3f 3c 40 aa 05 25 af 62 ee e9 ce 48 ba e8 08 88 |?<@..%.b...H....| +00000050 95 77 c7 f1 87 c6 ce 46 a2 50 2f 41 3c 8f bf 1a |.w.....F.P/A<...| +00000060 1e 1e 1b 39 9c |...9.| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 18 29 35 d7 c5 |..........0.)5..| -00000010 a2 31 3b 26 85 de 50 26 39 4d 16 22 58 a2 17 bd |.1;&..P&9M."X...| -00000020 4b 73 33 8d dc 3f 92 20 f2 ca 22 00 f5 31 db a7 |Ks3..?. .."..1..| -00000030 18 79 fc 71 87 68 a5 1d a6 db 33 17 03 01 00 20 |.y.q.h....3.... | -00000040 0d be 57 e4 12 6d 2d 3a 33 24 a0 0c c4 9b 27 09 |..W..m-:3$....'.| -00000050 85 e0 0e 42 04 79 21 9a bf 47 fa 0b 38 1a ce 8f |...B.y!..G..8...| -00000060 17 03 01 00 30 6d 27 f1 9b cf 55 4d 65 48 38 1b |....0m'...UMeH8.| -00000070 d9 dd 1d 5b 81 2f 10 a5 65 28 83 93 b3 b1 3a 72 |...[./..e(....:r| -00000080 f0 15 9a e5 9f 21 80 f1 59 a5 0e f1 0c 2b d1 0c |.....!..Y....+..| -00000090 d4 27 73 f3 7e 15 03 01 00 20 6f 08 27 3a d2 60 |.'s.~.... o.':.`| -000000a0 c3 27 bc 73 55 bb 43 53 e2 e0 87 16 ca 8f 49 f0 |.'.sU.CS......I.| -000000b0 88 a8 20 30 9d 42 86 d9 c3 36 |.. 0.B...6| +00000000 14 03 01 00 01 01 16 03 01 00 30 7b 30 af df 92 |..........0{0...| +00000010 2b ee 4d 02 e3 6c 6f 8b 72 32 16 0e 4d ba 71 0d |+.M..lo.r2..M.q.| +00000020 86 0d f5 7d fe dd 07 05 3d fe 70 9b 7f d9 2b c6 |...}....=.p...+.| +00000030 7e 04 82 5f ef 0c 0b c1 e7 a5 18 17 03 01 00 20 |~.._........... | +00000040 ad bd 43 a6 10 e8 e2 41 39 35 69 af a0 00 5f 81 |..C....A95i..._.| +00000050 1e 0a 5e 78 45 2f 66 27 cb 4f db 06 22 c0 ea 0f |..^xE/f'.O.."...| +00000060 17 03 01 00 30 16 69 7f fa 1c 89 36 9f 99 c6 49 |....0.i....6...I| +00000070 e6 0d 9a b7 81 00 75 f5 2d cc 89 e8 be 47 64 76 |......u.-....Gdv| +00000080 ef 34 27 a2 46 bd 8c 14 5b 15 67 ab f1 d9 30 c3 |.4'.F...[.g...0.| +00000090 df 96 a1 59 17 15 03 01 00 20 77 ea 6f e2 ae 81 |...Y..... w.o...| +000000a0 80 4f 37 7b ee 37 3f 40 df a3 e4 be 80 1e 3e 83 |.O7{.7?@......>.| +000000b0 9b 42 f7 95 50 af ab a5 60 54 |.B..P...`T| diff --git a/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial b/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial index b3d0f7d05b8..114ec3708ee 100644 --- a/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial +++ b/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 55 01 00 00 51 03 01 e0 8d 7b f2 8d |....U...Q....{..| -00000010 45 9f c5 40 1b be 81 05 a1 83 82 c1 54 4a c7 1c |E..@........TJ..| -00000020 f1 f8 d5 6c 7a ff 93 81 e2 a2 ba 00 00 04 c0 14 |...lz...........| +00000000 16 03 01 00 55 01 00 00 51 03 01 fb 2f 2f 8e 61 |....U...Q...//.a| +00000010 23 39 d1 13 76 62 4e f8 d5 40 82 a3 89 78 bf fe |#9..vbN..@...x..| +00000020 31 e9 60 d5 e1 e2 1c 54 7a bc 0b 00 00 04 c0 14 |1.`....Tz.......| 00000030 00 ff 01 00 00 24 00 0b 00 04 03 00 01 02 00 0a |.....$..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 16 00 00 00 17 00 00 |..........| @@ -51,42 +51,42 @@ 000002a0 fa e7 16 03 01 00 aa 0c 00 00 a6 03 00 1d 20 2f |.............. /| 000002b0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000002c0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 |.........._X.;t.| -000002d0 80 3d ff b7 ad d5 15 4f 10 6e 8a d2 ad 8a 6b 1b |.=.....O.n....k.| -000002e0 9d 6c f2 92 99 c7 d7 d8 07 d5 c7 77 09 22 41 4f |.l.........w."AO| -000002f0 7f ca 3e 8c 22 ba 2b f2 75 5f 47 c9 7e 0c 03 5d |..>.".+.u_G.~..]| -00000300 1a 66 c3 c8 f3 76 f0 f6 fa 03 40 3a 9b e7 2b 35 |.f...v....@:..+5| -00000310 bc c7 5e 62 a6 97 8a 1a 17 e3 13 4c 1f 88 39 2a |..^b.......L..9*| -00000320 5b cc 9c 65 df 27 1e b3 26 d7 46 3e 76 a9 ae 71 |[..e.'..&.F>v..q| -00000330 11 4d d6 10 b4 2e 30 37 a1 b4 ff 46 91 77 c7 4c |.M....07...F.w.L| -00000340 f9 8e e3 96 88 d2 1e c5 9d fb a1 be c6 ef 5d f0 |..............].| -00000350 52 16 03 01 00 04 0e 00 00 00 |R.........| +000002d0 80 ca 44 f4 0f ef d9 cb a9 88 61 a3 b4 f2 1b 9c |..D.......a.....| +000002e0 e9 a1 c2 c7 84 58 0e 3e ee 95 21 52 61 be 80 64 |.....X.>..!Ra..d| +000002f0 46 17 d5 c7 71 7c 43 41 70 2d 84 9a 49 1c bf 34 |F...q|CAp-..I..4| +00000300 f4 05 1a 0f 9c 00 c5 2d 64 37 84 34 5e d7 5c 06 |.......-d7.4^.\.| +00000310 50 99 f9 d5 a0 19 4b 2d aa 67 e4 17 c7 b4 23 26 |P.....K-.g....#&| +00000320 94 a1 cd e0 cb b1 33 9b e6 c6 a3 a7 25 93 87 7e |......3.....%..~| +00000330 37 ee 9c a0 42 b6 fd 60 59 02 4b 17 4a 4d f3 f2 |7...B..`Y.K.JM..| +00000340 2d 2a e7 8d 96 41 86 43 0a 7b 4e fc c0 7d 38 f6 |-*...A.C.{N..}8.| +00000350 f6 16 03 01 00 04 0e 00 00 00 |..........| >>> Flow 3 (client to server) -00000000 16 03 01 00 25 10 00 00 21 20 01 39 8b 2b 21 99 |....%...! .9.+!.| -00000010 fd fc b8 20 f1 51 97 c7 85 13 05 64 55 41 6b c4 |... .Q.....dUAk.| -00000020 1a 5e d5 b2 7c 8b 31 08 0f 78 14 03 01 00 01 01 |.^..|.1..x......| -00000030 16 03 01 00 30 d8 3b e6 9f f8 a8 b2 6b 8b fb 89 |....0.;.....k...| -00000040 71 3b 55 cd c3 c9 78 3c 45 1b 8d 5f 70 4f bd 64 |q;U...x>> Flow 4 (server to client) -00000000 16 03 01 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 01 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6d 2d 70 97 51 ed 14 ef 68 ca 42 c5 4c 71 8e 74 |m-p.Q...h.B.Lq.t| -00000030 d4 83 d6 4a 5b 69 f8 af 61 3a 98 83 19 d5 7c 60 |...J[i..a:....|`| -00000040 4a 1e f4 b7 26 b8 99 b5 45 6f a3 8d 97 63 5f 1b |J...&...Eo...c_.| -00000050 ab f4 84 59 db ce 99 ce b8 6a 23 d5 15 49 38 16 |...Y.....j#..I8.| -00000060 7e 51 5c e5 15 c0 58 7d c0 ee 59 1b e4 6e 1f c8 |~Q\...X}..Y..n..| -00000070 fc d4 2c 33 ed 0a 2b e0 78 04 64 4b 56 e4 af 61 |..,3..+.x.dKV..a| -00000080 c6 b5 7d f5 a0 86 9f e3 14 03 01 00 01 01 16 03 |..}.............| -00000090 01 00 30 73 2b f0 16 d3 a8 02 b3 73 98 5e 4e a0 |..0s+......s.^N.| -000000a0 ca 5b c4 50 fb 5a 92 11 43 97 e9 e3 16 9f 08 0a |.[.P.Z..C.......| -000000b0 56 73 e6 44 67 70 aa 3d bb c1 36 c8 63 1c 2b 51 |Vs.Dgp.=..6.c.+Q| -000000c0 1f 3b 81 17 03 01 00 20 4c 93 10 5c 01 e2 63 12 |.;..... L..\..c.| -000000d0 97 6b e1 89 fb e7 14 cf ec 70 d1 fe 6f ea 8b 09 |.k.......p..o...| -000000e0 63 5f 8c 8a 9e b5 ac b8 17 03 01 00 30 a1 ad dd |c_..........0...| -000000f0 92 ac a8 6e 77 ed c2 ed 59 b6 a8 41 ad 45 59 8c |...nw...Y..A.EY.| -00000100 4e 1d 16 36 57 e6 2f 47 3d 10 0f 36 04 00 b0 c1 |N..6W./G=..6....| -00000110 a7 94 25 8e 77 1e 69 20 41 6c c0 9d 26 15 03 01 |..%.w.i Al..&...| -00000120 00 20 c5 83 26 5d 20 cb 16 7e 27 63 d7 96 aa 96 |. ..&] ..~'c....| -00000130 37 19 2a 7a 18 d4 85 08 25 32 85 d5 b5 e3 4e 9b |7.*z....%2....N.| -00000140 98 f5 |..| +00000020 6d 2d 70 97 51 ed 14 ef 68 ca 42 c5 4c ed db 91 |m-p.Q...h.B.L...| +00000030 26 40 46 a4 da 9a 13 33 d7 75 7c e0 2f 98 9f 5a |&@F....3.u|./..Z| +00000040 9c a9 12 db 59 ba 75 b2 a1 cb cf f9 75 05 c3 55 |....Y.u.....u..U| +00000050 04 ee 2a 61 94 99 df 73 b3 0b 81 68 f3 49 38 16 |..*a...s...h.I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 07 a3 db 42 00 b3 4c |~Q\...X}R...B..L| +00000070 77 09 cd 17 5f c1 da 85 f3 09 46 d6 e9 ae 7c e8 |w..._.....F...|.| +00000080 3f 6a 74 38 f9 e7 de 23 0d 90 14 03 01 00 01 01 |?jt8...#........| +00000090 16 03 01 00 30 fa 7e 6e 18 87 06 c8 26 ae a0 34 |....0.~n....&..4| +000000a0 1a 58 05 9e 0c 47 60 93 8c 83 15 98 ad ee de 62 |.X...G`........b| +000000b0 53 6f 1b 44 90 45 d9 22 0b e3 d8 25 32 75 68 ae |So.D.E."...%2uh.| +000000c0 c4 39 b9 05 93 17 03 01 00 20 ac 7a ac 04 59 6a |.9....... .z..Yj| +000000d0 75 a3 26 96 49 c8 f3 ef 39 a6 1f 07 20 d2 e6 bf |u.&.I...9... ...| +000000e0 b8 06 69 55 97 6c c4 68 01 b9 17 03 01 00 30 8b |..iU.l.h......0.| +000000f0 67 6e 9a ea 62 2c dc eb aa 9b 57 e4 5f 82 14 c6 |gn..b,....W._...| +00000100 11 d2 44 e7 5a 9d 13 c0 3e 38 de a7 82 33 44 8e |..D.Z...>8...3D.| +00000110 10 c2 20 c8 6b d2 af 12 b5 44 84 17 a9 2a ec 15 |.. .k....D...*..| +00000120 03 01 00 20 56 39 68 ce 01 c1 52 dd 21 cb 65 a0 |... V9h...R.!.e.| +00000130 5d 28 00 d6 7f f0 c1 38 51 51 98 4f cb 13 5a 41 |](.....8QQ.O..ZA| +00000140 7b 34 be f8 |{4..| diff --git a/crypto/tls/testdata/Server-TLSv12-ALPN b/crypto/tls/testdata/Server-TLSv12-ALPN index ccd4a086a6e..6ee4bc8086d 100644 --- a/crypto/tls/testdata/Server-TLSv12-ALPN +++ b/crypto/tls/testdata/Server-TLSv12-ALPN @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 9d 01 00 00 99 03 03 f7 12 13 92 75 |...............u| -00000010 34 ab f3 e8 a2 19 2d 3c 0c 8b 9e c3 e8 22 7e d8 |4.....-<....."~.| -00000020 66 f9 08 88 70 9b cc 37 95 43 a7 00 00 04 cc a8 |f...p..7.C......| +00000000 16 03 01 00 9d 01 00 00 99 03 03 4c 3c dd 9a 33 |...........L<..3| +00000010 a3 3d c3 9d 54 4c a8 e7 d4 2d 20 59 11 bc 48 71 |.=..TL...- Y..Hq| +00000020 bc 5d 6b 24 fd 97 a2 30 4a 2f c8 00 00 04 cc a8 |.]k$...0J/......| 00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| @@ -57,35 +57,35 @@ 000002b0 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 |........... /.}.| 000002c0 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 000002d0 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 |......._X.;t....| -000002e0 2a 3d 85 27 96 fe 41 e2 5a cc 39 dd 8a 8e 64 73 |*=.'..A.Z.9...ds| -000002f0 ef 98 04 5c ac d2 8f 5e 55 b8 37 da 10 68 33 b8 |...\...^U.7..h3.| -00000300 63 83 e1 c9 9a e6 3a e9 c9 20 cc 57 58 e2 ba bc |c.....:.. .WX...| -00000310 e3 ac ab aa 08 e2 1e 6f 66 90 d7 66 c5 73 60 0d |.......of..f.s`.| -00000320 19 4f eb 99 9d d1 b1 91 36 80 b9 20 aa f5 d9 c8 |.O......6.. ....| -00000330 44 a7 99 c9 a6 4d 2c ff ca 4d 84 f2 a5 bf 02 c5 |D....M,..M......| -00000340 61 77 7e 4a e6 7c dd bf 48 fc a6 53 fb c4 d3 dd |aw~J.|..H..S....| -00000350 e6 20 b9 74 90 82 4a 3a 73 0a 81 74 07 a3 23 fe |. .t..J:s..t..#.| +000002e0 82 9a 38 98 24 59 07 8b a9 7e d3 9f c3 70 8d 87 |..8.$Y...~...p..| +000002f0 2d 1b 53 f3 36 96 4a 07 83 80 1e 62 23 b4 79 c9 |-.S.6.J....b#.y.| +00000300 93 48 0a 54 ad 03 5e 71 c3 69 d9 b7 be 93 c0 e8 |.H.T..^q.i......| +00000310 13 bd 10 67 b1 ea 8f f0 72 ed e1 54 b1 e5 a8 ca |...g....r..T....| +00000320 c7 b2 ac 2e 14 ab 6a 84 2b 97 e6 8f 68 1c e9 83 |......j.+...h...| +00000330 73 70 24 40 99 f7 86 2a c7 08 1f bc bd df a2 24 |sp$@...*.......$| +00000340 75 33 81 29 18 69 d5 5e 93 91 63 62 ee e9 8f b6 |u3.).i.^..cb....| +00000350 fc d1 00 5d b2 b5 cc 5f c9 83 8d fd f8 dd 7a cd |...]..._......z.| 00000360 16 03 03 00 04 0e 00 00 00 |.........| >>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 d1 bb f1 17 6c 41 |....%...! ....lA| -00000010 8f 14 84 d2 98 99 30 0c 8a 00 4c 39 37 15 f5 be |......0...L97...| -00000020 81 8d 08 e0 11 c1 f7 65 43 0b 14 03 03 00 01 01 |.......eC.......| -00000030 16 03 03 00 20 ab 15 bb 47 30 42 c9 7d 45 f8 5d |.... ...G0B.}E.]| -00000040 21 79 3b 4d 5e a9 99 f5 7d f3 4e 7e ba b9 9b 30 |!y;M^...}.N~...0| -00000050 b6 14 4d ba f9 |..M..| +00000000 16 03 03 00 25 10 00 00 21 20 61 d8 61 58 30 ba |....%...! a.aX0.| +00000010 44 5b 31 35 e3 4e 92 87 d0 10 0c 83 96 98 b5 73 |D[15.N.........s| +00000020 31 40 7a fd 78 8a cf b4 af 53 14 03 03 00 01 01 |1@z.x....S......| +00000030 16 03 03 00 20 14 80 2b 46 28 9e a8 1b d5 9a bd |.... ..+F(......| +00000040 6c da 22 62 a9 7d d8 c1 e5 d7 63 6f 26 3f ca 1c |l."b.}....co&?..| +00000050 5e 53 8b 3c f3 |^S.<.| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c f3 5c b9 |o-|+Q...h.B.L.\.| -00000030 84 7d 30 9e 2f 9d 4d 0e 59 b4 28 fd 17 10 cd 1e |.}0./.M.Y.(.....| -00000040 1c d3 2c 5e d9 dc db 26 d0 b9 00 4b 0a 13 54 90 |..,^...&...K..T.| -00000050 f2 7b 68 75 6b 00 34 66 9e 43 29 06 16 49 38 16 |.{huk.4f.C)..I8.| -00000060 7e 51 5c e5 15 c0 58 7d 52 0b 16 21 d8 2c e8 c8 |~Q\...X}R..!.,..| -00000070 8e 3a f6 aa fa 21 45 4a 17 02 67 7d 93 1c 95 88 |.:...!EJ..g}....| -00000080 36 a5 19 53 74 74 81 e1 14 03 03 00 01 01 16 03 |6..Stt..........| -00000090 03 00 20 3d 66 04 37 0c 40 cc 20 2c 1c 16 ba 05 |.. =f.7.@. ,....| -000000a0 d6 7b 40 04 27 40 6f cc d7 af 68 fb 32 49 6c 4f |.{@.'@o...h.2IlO| -000000b0 f3 01 bf 17 03 03 00 1d 99 10 78 bc fa 7e 8a 86 |..........x..~..| -000000c0 4c b8 e4 7c e2 79 70 eb ad 33 44 e1 ab 7a c9 ae |L..|.yp..3D..z..| -000000d0 47 fe 39 50 d1 15 03 03 00 12 9e 9a be b0 55 c3 |G.9P..........U.| -000000e0 3a 5f 5c e0 4b 8f 4f 81 52 d3 89 09 |:_\.K.O.R...| +00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c a3 4e 47 |o-|+Q...h.B.L.NG| +00000030 75 8d 90 24 a8 60 43 a8 3b 00 81 b1 1d 41 ce bf |u..$.`C.;....A..| +00000040 ec 75 e9 32 6b 9b 21 9f 0f 56 27 b2 e5 9e 9a 01 |.u.2k.!..V'.....| +00000050 aa c7 63 81 8b 90 45 fa 64 75 96 e3 c8 49 38 16 |..c...E.du...I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 07 32 1b 54 23 7f 75 |~Q\...X}R.2.T#.u| +00000070 8a 30 1c 6a 94 57 27 7d 06 25 05 b7 ae ce 5c a4 |.0.j.W'}.%....\.| +00000080 58 21 47 f2 04 bc 3a f1 6d 20 14 03 03 00 01 01 |X!G...:.m ......| +00000090 16 03 03 00 20 94 0c cf 54 2b fb 49 26 19 d4 06 |.... ...T+.I&...| +000000a0 0e b6 71 b5 d9 24 f6 d1 99 36 78 1c 96 b4 12 e0 |..q..$...6x.....| +000000b0 20 5a 2a a7 ad 17 03 03 00 1d 19 36 ef 7d 53 24 | Z*........6.}S$| +000000c0 0c 5e 48 24 c6 ad 91 ca 44 0d 2e fb 10 fd 58 2f |.^H$....D.....X/| +000000d0 86 5c be c6 64 01 c6 15 03 03 00 12 26 94 16 38 |.\..d.......&..8| +000000e0 6c 23 4e 29 03 96 c6 6a a8 af 32 0b 2e 9e |l#N)...j..2...| diff --git a/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback b/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback index 070201253d2..a453fcc5227 100644 --- a/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback +++ b/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 a6 01 00 00 a2 03 03 ea e2 1b 90 0e |................| -00000010 91 d5 9f b2 c6 ee 72 37 19 f5 14 cd ca a9 ca 03 |......r7........| -00000020 98 c4 2e d4 85 05 4a a5 02 e1 4b 00 00 04 cc a8 |......J...K.....| +00000000 16 03 01 00 a6 01 00 00 a2 03 03 74 b9 ce 14 2f |...........t.../| +00000010 85 a9 93 bf 60 4e 5c 5c 6e 47 34 cf b8 27 f8 dc |....`N\\nG4..'..| +00000020 b1 5b a8 eb e0 fa da a0 1b b6 9c 00 00 04 cc a8 |.[..............| 00000030 00 ff 01 00 00 75 00 0b 00 04 03 00 01 02 00 0a |.....u..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.| @@ -56,35 +56,35 @@ 000002a0 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2f |.............. /| 000002b0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000002c0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 |.........._X.;t.| -000002d0 04 00 80 85 e9 a6 5c 79 bc db ed 97 fb 30 ca fd |......\y.....0..| -000002e0 32 13 19 3f da 6f fd c1 11 74 fe e9 6f 60 ec 7e |2..?.o...t..o`.~| -000002f0 48 7e 17 33 9b 8d 2a c2 82 e0 18 38 f3 0f 20 27 |H~.3..*....8.. '| -00000300 81 0f c9 47 bf 5f 2b 2f 65 1c 6b e3 b7 72 85 46 |...G._+/e.k..r.F| -00000310 5c 15 dc fd e6 be cf 50 51 62 f5 d9 17 e2 e8 bf |\......PQb......| -00000320 08 7f 37 71 91 88 83 7f e3 90 66 66 c4 d8 60 25 |..7q......ff..`%| -00000330 53 f7 9f 44 20 89 48 ff c2 3b 6d 21 e5 8c dc e5 |S..D .H..;m!....| -00000340 42 ea d8 14 93 96 2f 53 24 66 e7 bb e7 2c 1f 92 |B...../S$f...,..| -00000350 90 80 23 16 03 03 00 04 0e 00 00 00 |..#.........| +000002d0 04 00 80 22 97 55 0d 4c fe 5e 4e 45 b7 9b b2 f8 |...".U.L.^NE....| +000002e0 29 c7 7a 33 b5 e0 06 92 4f b3 6e 67 ad 4e 69 20 |).z3....O.ng.Ni | +000002f0 e5 82 b6 93 84 52 05 fd 99 d1 94 67 e4 7d bc 1d |.....R.....g.}..| +00000300 f7 16 d7 24 95 61 db ed 92 16 11 ee c1 c5 6f 82 |...$.a........o.| +00000310 8e 6b 10 69 31 d2 17 1a 6f 25 a0 d5 4b 7e c9 ba |.k.i1...o%..K~..| +00000320 13 3e c4 94 46 63 e2 6e c6 ca d0 e4 09 5a 2a 39 |.>..Fc.n.....Z*9| +00000330 12 c0 fc 37 14 4e a8 1f 74 4e 44 86 1a 29 d4 a0 |...7.N..tND..)..| +00000340 5f e5 0a 22 6c 09 78 29 be 33 a5 2c d9 b3 5f ec |_.."l.x).3.,.._.| +00000350 f1 5e 87 16 03 03 00 04 0e 00 00 00 |.^..........| >>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 e8 d1 46 5e 70 b5 |....%...! ..F^p.| -00000010 34 1c 6f cd be f0 86 24 2a d6 55 ae 97 de 52 0c |4.o....$*.U...R.| -00000020 67 10 a0 02 ed ae f8 47 aa 52 14 03 03 00 01 01 |g......G.R......| -00000030 16 03 03 00 20 52 cf 5d 07 bb bc e8 86 d4 f4 3e |.... R.].......>| -00000040 49 51 a7 1d f5 df 10 c4 5a 77 37 ba 68 3d 4e c5 |IQ......Zw7.h=N.| -00000050 11 ac 67 b7 e2 |..g..| +00000000 16 03 03 00 25 10 00 00 21 20 a4 f2 f3 f8 81 68 |....%...! .....h| +00000010 6f 8d d5 2c 93 fe ee cf f6 28 ae 06 9f 81 fa 0d |o..,.....(......| +00000020 ac 31 2b cf 05 4e cb a0 b3 14 14 03 03 00 01 01 |.1+..N..........| +00000030 16 03 03 00 20 ca 3e f2 cd 68 42 34 26 61 40 29 |.... .>..hB4&a@)| +00000040 dd 71 e1 52 b7 0e ec 1f 77 8e 1d 1b 95 dd 07 4f |.q.R....w......O| +00000050 c4 4d d8 02 83 |.M...| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c 26 1d 23 |o-|+Q...h.B.L&.#| -00000030 c4 90 54 85 8b 21 f5 0d e8 48 f2 5f 4e 6b f1 25 |..T..!...H._Nk.%| -00000040 e8 46 8a e5 3c 09 57 df dd 37 a7 57 c5 a5 28 5a |.F..<.W..7.W..(Z| -00000050 21 83 2a 98 4b a5 44 aa 5b cc 30 e9 62 49 38 16 |!.*.K.D.[.0.bI8.| -00000060 7e 51 5c e5 15 c0 58 7d a4 aa c5 93 39 bb e2 b6 |~Q\...X}....9...| -00000070 4f c4 3e 1e 03 dc 46 b1 f3 0d d2 61 6c 1e c5 e1 |O.>...F....al...| -00000080 8f 18 2a 3c 85 83 c4 33 14 03 03 00 01 01 16 03 |..*<...3........| -00000090 03 00 20 63 76 4f b3 77 4d 63 6c eb 73 f3 b2 ec |.. cvO.wMcl.s...| -000000a0 b8 49 3e c5 81 d5 53 0c 96 77 2f 3f 52 d0 e1 5b |.I>...S..w/?R..[| -000000b0 62 fa 0b 17 03 03 00 1d 2f 60 09 31 db e9 c5 23 |b......./`.1...#| -000000c0 98 5c 46 23 a6 58 80 66 7d 50 84 f1 42 b8 65 65 |.\F#.X.f}P..B.ee| -000000d0 77 2d d2 e4 be 15 03 03 00 12 b7 e8 e1 13 04 68 |w-.............h| -000000e0 d5 21 c8 98 db 1b 1c 6e 4f b5 0b 9c |.!.....nO...| +00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c 23 bb 4f |o-|+Q...h.B.L#.O| +00000030 57 15 7b bb 5c 23 ff bd b0 3b c9 ce d7 8e b9 d8 |W.{.\#...;......| +00000040 b6 35 dd 0b 5b fd 3f bf c6 c9 74 86 d4 4e 1c 22 |.5..[.?...t..N."| +00000050 fb 4e ea 39 16 d3 9d 08 c8 08 c8 94 c7 49 38 16 |.N.9.........I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 07 e6 23 d9 47 91 c4 |~Q\...X}R..#.G..| +00000070 55 a3 14 46 22 5a 68 ec 70 f1 cd 8b e0 36 5d 20 |U..F"Zh.p....6] | +00000080 bb 33 6b d2 cc e0 bc 81 f6 ba 14 03 03 00 01 01 |.3k.............| +00000090 16 03 03 00 20 06 6c 46 46 01 02 e9 42 de 4a dc |.... .lFF...B.J.| +000000a0 4b 55 15 6d e4 2c da 02 67 af 08 f1 15 f6 5a 72 |KU.m.,..g.....Zr| +000000b0 0b 70 d3 28 ba 17 03 03 00 1d 5b 4f 16 d3 78 dd |.p.(......[O..x.| +000000c0 fb cb 38 70 cc dc 26 36 99 ad 67 e3 dc 2b c8 62 |..8p..&6..g..+.b| +000000d0 1f a1 ad 3b e2 fd d7 15 03 03 00 12 e4 ca da 87 |...;............| +000000e0 78 97 b2 b3 27 0f 3e 1a 97 8d ab fc 7c b9 |x...'.>.....|.| diff --git a/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured b/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured index 79f0748af40..97d300d76b9 100644 --- a/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured +++ b/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 9d 01 00 00 99 03 03 19 26 ad 3f c0 |............&.?.| -00000010 d6 a0 cc ac 9b 2a 91 d3 1a d5 96 78 5f 7c 3f e0 |.....*.....x_|?.| -00000020 23 08 75 a1 ca cb aa da d7 c8 0b 00 00 04 cc a8 |#.u.............| +00000000 16 03 01 00 9d 01 00 00 99 03 03 23 13 3f 28 85 |...........#.?(.| +00000010 56 f7 0f d1 b4 ee 5f 18 a0 58 8c c5 83 a4 13 24 |V....._..X.....$| +00000020 9b 53 29 6e 28 35 a8 8c 0e 07 2a 00 00 04 cc a8 |.S)n(5....*.....| 00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| @@ -56,35 +56,35 @@ 000002a0 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2f |.............. /| 000002b0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000002c0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 |.........._X.;t.| -000002d0 04 00 80 4f 9e 64 41 a6 8a 41 ab 9c c8 09 3e 94 |...O.dA..A....>.| -000002e0 ee d2 9b ad 1b 3e a9 3c 7b 43 96 95 eb 4d b5 04 |.....>.<{C...M..| -000002f0 1a 5f 0c b2 b3 a6 2c a4 e6 78 a8 b8 d5 6c 7f d0 |._....,..x...l..| -00000300 16 e8 56 31 e0 4a 69 d3 6b 27 18 a3 4e f5 d1 6a |..V1.Ji.k'..N..j| -00000310 36 15 b5 fc 4d 15 50 90 a0 30 b9 49 3d ac 8c 84 |6...M.P..0.I=...| -00000320 d2 15 31 70 df e5 a6 97 d0 64 f7 1d 8a a1 87 4d |..1p.....d.....M| -00000330 3c ee da 69 20 e4 31 67 ca f2 c0 09 ee 13 7c 78 |<..i .1g......|x| -00000340 d6 c2 c0 39 e0 b8 00 52 a9 bf d0 99 e0 b0 66 70 |...9...R......fp| -00000350 46 ae 62 16 03 03 00 04 0e 00 00 00 |F.b.........| +000002d0 04 00 80 66 f8 99 59 3a 3a 64 36 75 11 53 eb 34 |...f..Y::d6u.S.4| +000002e0 1d d7 56 1b fb 73 58 63 69 2d 3d b5 d0 05 ce 4d |..V..sXci-=....M| +000002f0 6d 6e 49 46 c2 ad 91 43 de b3 63 12 4b e6 e2 c8 |mnIF...C..c.K...| +00000300 59 09 09 45 f2 b8 1e 95 71 b2 38 60 78 36 c5 46 |Y..E....q.8`x6.F| +00000310 15 85 66 4b 83 e2 6f 07 df 3e 87 60 eb 85 2d 01 |..fK..o..>.`..-.| +00000320 c4 ae 50 b8 0e e5 19 b4 1d a4 90 af 97 b7 87 9e |..P.............| +00000330 cb 3a 13 1f ec 78 6c d9 5d 14 03 b7 4b 8b 8d 92 |.:...xl.]...K...| +00000340 06 cf a3 dc 59 30 36 0f 7f 24 11 ca b8 ff 46 4b |....Y06..$....FK| +00000350 0c 4e c2 16 03 03 00 04 0e 00 00 00 |.N..........| >>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 b0 1a 5b c3 55 5f |....%...! ..[.U_| -00000010 0b b8 f3 69 ba 4f 49 93 05 0f b1 f1 d7 6b 6c 0c |...i.OI......kl.| -00000020 98 d0 22 78 0c ad 15 6b 24 5b 14 03 03 00 01 01 |.."x...k$[......| -00000030 16 03 03 00 20 9d aa 3f 17 b3 16 88 d5 44 3d 03 |.... ..?.....D=.| -00000040 3c 3c 8d 92 f1 2f e4 38 cc 42 20 2f ef 6a 29 c6 |<<.../.8.B /.j).| -00000050 5c ca 44 81 f6 |\.D..| +00000000 16 03 03 00 25 10 00 00 21 20 16 8d 5b 4a f7 e1 |....%...! ..[J..| +00000010 c0 dd 5d e2 82 7d 4e c6 ef 66 ef 87 50 85 bf 0d |..]..}N..f..P...| +00000020 b5 3f 03 cc 64 f4 48 93 79 27 14 03 03 00 01 01 |.?..d.H.y'......| +00000030 16 03 03 00 20 2c 69 26 7b 1b 84 2b 1d 33 43 cf |.... ,i&{..+.3C.| +00000040 95 c5 72 d6 7a 88 8f f9 aa 82 72 f4 02 c5 6e aa |..r.z.....r...n.| +00000050 a9 f7 f0 b9 44 |....D| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c 9a f3 2b |o-|+Q...h.B.L..+| -00000030 7a 66 76 26 4f 73 12 14 ef a1 f4 8c c2 08 03 42 |zfv&Os.........B| -00000040 4d d5 f9 d7 ab 31 78 51 f3 f4 94 49 5f 9d bf 23 |M....1xQ...I_..#| -00000050 b2 11 7b ac 42 df 71 1a 37 db 64 99 a0 49 38 16 |..{.B.q.7.d..I8.| -00000060 7e 51 5c e5 15 c0 58 7d 2d 89 ac 0d 05 31 27 ae |~Q\...X}-....1'.| -00000070 85 ff 27 56 24 4c 26 b3 bc 6c f6 20 80 dd bd ba |..'V$L&..l. ....| -00000080 a3 34 c2 32 a8 58 1b b9 14 03 03 00 01 01 16 03 |.4.2.X..........| -00000090 03 00 20 74 e1 8a e6 a6 02 0d f7 e1 28 3a f4 c4 |.. t........(:..| -000000a0 a6 8c 32 81 84 85 ec 58 6a 10 8a 6d c4 cc 10 3a |..2....Xj..m...:| -000000b0 32 3e df 17 03 03 00 1d fd a8 94 23 3e 5d 96 b1 |2>.........#>]..| -000000c0 68 a6 24 55 bf 29 08 93 c7 7b 9b 05 fc 0b 97 ff |h.$U.)...{......| -000000d0 7c 93 b0 34 82 15 03 03 00 12 43 9f 44 e4 63 e7 ||..4......C.D.c.| -000000e0 3c 30 a5 da 9f 58 ac 01 e4 e2 a7 30 |<0...X.....0| +00000020 6f 2d 7c 2b 51 ed 14 ef 68 ca 42 c5 4c 2e ba 80 |o-|+Q...h.B.L...| +00000030 92 a2 2f 66 80 b9 56 b8 7b be 8f 7f 3e f1 92 8d |../f..V.{...>...| +00000040 bf a9 6d 23 58 04 c5 70 85 af a7 db e4 0f e5 87 |..m#X..p........| +00000050 6e aa a1 58 2a 7c 3f 9b 15 36 ac a3 00 49 38 16 |n..X*|?..6...I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 07 ff f3 10 e5 6f 3a |~Q\...X}R.....o:| +00000070 6f e9 dd 79 00 6d 46 a8 9d a3 6c 3b 1b 39 da 98 |o..y.mF...l;.9..| +00000080 5a 36 f1 64 1f a6 4b f8 2b ff 14 03 03 00 01 01 |Z6.d..K.+.......| +00000090 16 03 03 00 20 d1 e3 4a cc 06 f0 a9 b6 f7 66 2d |.... ..J......f-| +000000a0 3d 07 70 e2 93 39 a1 2a c2 72 f3 e7 b3 ca a0 77 |=.p..9.*.r.....w| +000000b0 ff cf 9b 0f 2f 17 03 03 00 1d 4b e5 61 b4 4c 6b |..../.....K.a.Lk| +000000c0 b0 ca 5e e4 96 7b f2 18 9a c2 19 b2 be c2 39 8b |..^..{........9.| +000000d0 ee 88 e7 53 27 3a 8d 15 03 03 00 12 2a 21 52 fc |...S':......*!R.| +000000e0 3b ae 6e fb ac 9c 42 bc 1a 7d 6b 8d 84 5d |;.n...B..}k..]| diff --git a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven index 41ed6c4e1b0..73d54e65790 100644 --- a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven +++ b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 6d 01 00 00 69 03 03 5e 92 9d 30 27 |....m...i..^..0'| -00000010 23 da fa a0 07 30 03 c8 bd 60 f2 db e9 5e b3 fc |#....0...`...^..| -00000020 65 d3 c5 e1 49 35 63 86 53 ec 87 00 00 04 00 2f |e...I5c.S....../| +00000000 16 03 01 00 6d 01 00 00 69 03 03 5e 1c 8d af f1 |....m...i..^....| +00000010 4a ab 9d e1 c7 9c 85 c3 ab b8 84 84 ee 39 66 0b |J............9f.| +00000020 6d d7 b2 3b 7b bf 4e d1 90 a4 92 00 00 04 00 2f |m..;{.N......../| 00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| 00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| 00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| @@ -49,10 +49,10 @@ 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 23 0d 00 00 |.\!.;.......#...| -000002a0 1f 02 01 40 00 18 08 04 04 03 08 07 08 05 08 06 |...@............| -000002b0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 00 |................| -000002c0 16 03 03 00 04 0e 00 00 00 |.........| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 1f 0d 00 00 |.\!.;...........| +000002a0 1b 02 01 40 00 14 08 04 04 03 08 07 08 05 08 06 |...@............| +000002b0 04 01 05 01 06 01 05 03 06 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| 00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| @@ -87,40 +87,40 @@ 000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| 000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| -00000210 03 03 00 86 10 00 00 82 00 80 02 50 e4 cc a3 ad |...........P....| -00000220 fb 33 24 a1 b3 0a 7c 0f 00 e6 1a 06 2b 9f 1e 1f |.3$...|.....+...| -00000230 cc b8 b2 80 90 e7 86 20 32 40 06 ac 1b b0 41 b7 |....... 2@....A.| -00000240 0d 9c 4c 41 90 01 0b 7a 7e b2 b2 46 39 dc 51 25 |..LA...z~..F9.Q%| -00000250 98 e0 b9 ec 36 fc 08 64 f0 51 2a 41 e1 e5 61 3d |....6..d.Q*A..a=| -00000260 fc 07 c1 9b 1f 6f 48 d4 1f 46 bf 14 e6 92 61 1a |.....oH..F....a.| -00000270 bd 5f 25 1f 5e b1 3c ac c7 58 63 02 0d 3a e0 d6 |._%.^.<..Xc..:..| -00000280 e9 39 fc ec 59 66 2e 91 b2 65 37 eb a8 b5 60 d9 |.9..Yf...e7...`.| -00000290 49 05 9f 6f cc 71 79 bb f7 68 16 03 03 00 93 0f |I..o.qy..h......| -000002a0 00 00 8f 04 03 00 8b 30 81 88 02 42 00 bd 6a 29 |.......0...B..j)| -000002b0 21 06 1a e2 67 a1 7f 10 ab ca 3f 74 5a bc 2f 5d |!...g.....?tZ./]| -000002c0 53 d0 59 90 f2 d0 b4 2d 75 47 67 0b 67 55 b6 4f |S.Y....-uGg.gU.O| -000002d0 75 7d 32 d8 a7 25 c8 4c 90 0b 56 65 be 60 5d ee |u}2..%.L..Ve.`].| -000002e0 f7 b3 80 79 26 e5 25 1d 17 cc d8 36 fc 39 02 42 |...y&.%....6.9.B| -000002f0 01 c3 32 d6 f2 59 9e 10 c8 bf 7f 74 27 a1 00 df |..2..Y.....t'...| -00000300 55 05 f0 b3 81 a1 6e 10 a6 fb 0b e4 1c 3f 62 02 |U.....n......?b.| -00000310 c9 cc c2 4b 97 ad 0c 88 98 07 6c 98 6d db 9d 9f |...K......l.m...| -00000320 68 a0 56 ab 5f f9 a2 21 33 86 64 53 de 37 ff 68 |h.V._..!3.dS.7.h| -00000330 04 9d 14 03 03 00 01 01 16 03 03 00 40 85 14 34 |............@..4| -00000340 d6 74 a9 d0 0b e9 1f 34 a9 e9 6c cf 5a ac 88 22 |.t.....4..l.Z.."| -00000350 51 4d ae 16 05 dd 9e c1 36 5e e3 cf b1 5a b5 48 |QM......6^...Z.H| -00000360 6c 24 b1 d6 fb 7f 03 6a 98 41 90 de 6d c7 b2 49 |l$.....j.A..m..I| -00000370 d9 a3 c7 45 ff 18 7c f7 a4 cf 05 59 87 |...E..|....Y.| +00000210 03 03 00 86 10 00 00 82 00 80 b1 e6 1d 71 51 c1 |.............qQ.| +00000220 3a bd 0a 32 95 14 0c 83 7a 2b ec 89 24 f2 29 d8 |:..2....z+..$.).| +00000230 72 84 ae 13 33 90 58 93 b6 46 6c 54 11 54 5b d3 |r...3.X..FlT.T[.| +00000240 59 da 02 4a de 2a 56 67 04 32 3b 44 6b ac 6d 6c |Y..J.*Vg.2;Dk.ml| +00000250 c5 de 9d b2 9e 7b ec 27 05 9d 47 6d a1 0b 50 71 |.....{.'..Gm..Pq| +00000260 ea 19 cc 60 5e db 6c 2f 06 b7 6e ce 51 bf 93 a9 |...`^.l/..n.Q...| +00000270 0e c7 85 c1 83 d2 ac fe 6a d2 a9 bd b3 54 4f 45 |........j....TOE| +00000280 4b e4 40 68 fb 30 21 ec 1c fc 76 a6 db 8b e1 46 |K.@h.0!...v....F| +00000290 8c 0c 56 1f c0 e5 9b 2c 54 eb 16 03 03 00 93 0f |..V....,T.......| +000002a0 00 00 8f 04 03 00 8b 30 81 88 02 42 01 11 9a de |.......0...B....| +000002b0 07 19 df 8b d0 56 e7 b5 b0 d2 d4 c1 32 58 93 88 |.....V......2X..| +000002c0 ea a6 73 86 f9 e6 be b5 c5 1f d6 0d da 28 59 89 |..s..........(Y.| +000002d0 21 73 fe e8 30 b9 f0 d1 01 d3 e0 54 79 a6 67 0d |!s..0......Ty.g.| +000002e0 84 88 94 2c b9 b6 0e 19 06 34 cc f1 5f 01 02 42 |...,.....4.._..B| +000002f0 00 fe 02 83 e8 46 a8 5f ef 5a f0 e1 6f 3f 73 b9 |.....F._.Z..o?s.| +00000300 0f a1 64 db a7 c4 fb 1e 9f ac da 33 ac a2 7f ff |..d........3....| +00000310 64 c1 26 37 17 41 c0 5e f4 37 5c 76 23 7d 92 3a |d.&7.A.^.7\v#}.:| +00000320 ea 35 7f 83 03 7b a4 65 44 5d fb 84 08 39 c7 90 |.5...{.eD]...9..| +00000330 cc 4a 14 03 03 00 01 01 16 03 03 00 40 7b 06 98 |.J..........@{..| +00000340 ff f7 d5 a1 68 60 23 25 bc df 12 27 7f 64 1e c8 |....h`#%...'.d..| +00000350 bc 6d 26 28 29 d0 9f 56 6a f1 5b cd 4e 17 6c 32 |.m&()..Vj.[.N.l2| +00000360 15 b9 7a 55 02 9b 66 1c e3 97 40 26 69 7b e7 02 |..zU..f...@&i{..| +00000370 b0 37 d1 ec ed 96 2e 92 5a 5f 90 c1 be |.7......Z_...| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 63 1a 77 66 2a |...........c.wf*| -00000020 49 3a b2 17 83 74 e1 d9 70 96 de 01 84 09 f4 88 |I:...t..p.......| -00000030 c3 e7 3b 65 11 6f 13 32 b8 b4 f4 41 ca 6a d6 d7 |..;e.o.2...A.j..| -00000040 51 a3 a1 f0 2d 5b b4 55 29 f9 d3 17 03 03 00 40 |Q...-[.U)......@| +00000010 00 00 00 00 00 00 00 00 00 00 00 0f e2 df ef c7 |................| +00000020 0e 11 83 70 ba a8 fa 90 e3 d5 df 76 dd 7a f1 63 |...p.......v.z.c| +00000030 ca a3 12 c7 42 45 ae 1a a3 0f 3b 4c 46 52 91 8e |....BE....;LFR..| +00000040 bf df 21 be cb ed 93 12 8a ba 88 17 03 03 00 40 |..!............@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 d7 30 0f 03 89 22 4c 19 5f 06 a7 4b 95 59 91 52 |.0..."L._..K.Y.R| -00000070 2a 65 ab 99 cb 71 99 8b 13 82 44 92 6b ff 59 07 |*e...q....D.k.Y.| -00000080 28 ca 01 68 ab ad ba ee 6c 6a 19 0b e5 6d 82 24 |(..h....lj...m.$| +00000060 12 fd 68 02 2d 6e aa 2f df e4 0b a1 2c 13 e1 23 |..h.-n./....,..#| +00000070 f9 78 4b 18 a3 1f 28 78 4d f6 25 83 4c 0c 8c df |.xK...(xM.%.L...| +00000080 8b ed a9 b2 87 8c 95 e3 87 8e 71 ad d9 23 05 91 |..........q..#..| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 fc 07 f4 d4 bb 24 a3 f1 cf dc 3c |..........$....<| -000000b0 ac 14 63 50 32 34 fd 73 c0 eb f2 78 7b 3b ea 58 |..cP24.s...x{;.X| -000000c0 cc 3e ff 7f e5 |.>...| +000000a0 00 00 00 00 00 80 9a 8c 0e 27 b9 7a f9 61 a4 a6 |.........'.z.a..| +000000b0 4e c9 24 02 ce 1c 93 5c 5a 7a c9 1e 5f b2 a1 9b |N.$....\Zz.._...| +000000c0 e3 0d 47 85 ab |..G..| diff --git a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given index f8cc96058df..4ca8a034ed2 100644 --- a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given +++ b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 6d 01 00 00 69 03 03 8a fe ad ad 75 |....m...i......u| -00000010 e4 8c bf bf b7 b6 66 14 92 eb 84 85 9c c8 a7 66 |......f........f| -00000020 04 2a d0 63 5e a6 bf 85 e9 4f 49 00 00 04 00 2f |.*.c^....OI..../| +00000000 16 03 01 00 6d 01 00 00 69 03 03 73 b2 f2 a9 ed |....m...i..s....| +00000010 88 e0 79 65 b4 3b 58 0d b2 d8 ab cf d7 12 12 c6 |..ye.;X.........| +00000020 99 f9 36 75 d3 f8 3e 94 cf 39 25 00 00 04 00 2f |..6u..>..9%..../| 00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| 00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| 00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| @@ -49,10 +49,10 @@ 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 23 0d 00 00 |.\!.;.......#...| -000002a0 1f 02 01 40 00 18 08 04 04 03 08 07 08 05 08 06 |...@............| -000002b0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 00 |................| -000002c0 16 03 03 00 04 0e 00 00 00 |.........| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 1f 0d 00 00 |.\!.;...........| +000002a0 1b 02 01 40 00 14 08 04 04 03 08 07 08 05 08 06 |...@............| +000002b0 04 01 05 01 06 01 05 03 06 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 |....<...8..5..20| 00000010 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 17 d1 81 |...0............| @@ -74,36 +74,36 @@ 00000110 8a 4e 34 40 39 d6 b3 10 dc 19 fe a0 22 71 b3 f5 |.N4@9......."q..| 00000120 8f a1 58 0d cd f4 f1 85 24 bf e6 3d 14 df df ed |..X.....$..=....| 00000130 0e e1 17 d8 11 a2 60 d0 8a 37 23 2a c2 46 aa 3a |......`..7#*.F.:| -00000140 08 16 03 03 00 86 10 00 00 82 00 80 77 8b 9f 34 |............w..4| -00000150 b4 db a7 0d 5b ed 1b 2f 4a 41 64 f5 ce 4a 00 7c |....[../JAd..J.|| -00000160 91 32 b3 cf 61 18 41 04 ae fa 3b 14 de 19 0e 64 |.2..a.A...;....d| -00000170 f9 ec 75 a6 48 7e 28 57 26 f5 1c 75 1d 42 73 fc |..u.H~(W&..u.Bs.| -00000180 11 51 2b ef e5 08 83 ac 17 ec 78 b8 5b 14 84 c9 |.Q+.......x.[...| -00000190 bc 7f 22 fd 54 69 7a 82 36 c7 21 bc d6 04 c4 e7 |..".Tiz.6.!.....| -000001a0 bc 48 c8 72 56 5d 1e 65 41 21 0a 26 85 a0 d8 c3 |.H.rV].eA!.&....| -000001b0 50 f0 b6 07 25 ee 79 b8 f5 e6 17 85 d4 09 e7 d7 |P...%.y.........| -000001c0 ab 8f 17 cb c2 13 a0 5a 50 cb e4 a7 16 03 03 00 |.......ZP.......| -000001d0 48 0f 00 00 44 08 07 00 40 b7 24 50 46 db d4 8c |H...D...@.$PF...| -000001e0 68 17 f5 5e 79 a9 80 8c 40 23 92 33 4e 1e cc ee |h..^y...@#.3N...| -000001f0 d5 35 4d b8 2a 52 f0 7f 50 8e c6 d5 5f bc 08 35 |.5M.*R..P..._..5| -00000200 a2 6d db cb 96 52 ec 92 c7 62 c7 59 ab d8 6f 9d |.m...R...b.Y..o.| -00000210 d7 46 35 71 28 41 89 59 02 14 03 03 00 01 01 16 |.F5q(A.Y........| -00000220 03 03 00 40 3e 12 44 bc c6 3d 88 71 ba d3 0c 26 |...@>.D..=.q...&| -00000230 20 72 b0 7f 25 83 9f fd 77 c1 f5 1e 47 28 2e 60 | r..%...w...G(.`| -00000240 53 e0 ac 52 e8 94 e4 87 90 3f af f3 a4 c0 d3 ba |S..R.....?......| -00000250 fe b7 06 54 f7 13 33 36 47 8f 5e 45 22 84 18 3a |...T..36G.^E"..:| -00000260 1f 14 21 85 |..!.| +00000140 08 16 03 03 00 86 10 00 00 82 00 80 1c aa 0a c6 |................| +00000150 76 22 2b bc 67 c7 db 5a 59 0c 2b 1d 1a 66 9b c5 |v"+.g..ZY.+..f..| +00000160 55 ac 80 bf 23 11 68 96 82 df 44 cf bc 44 4f 54 |U...#.h...D..DOT| +00000170 ce 0c 32 01 59 5e 3e a8 28 e1 33 7d 7d fb 2a 87 |..2.Y^>.(.3}}.*.| +00000180 53 d1 32 25 b8 29 5a 5e 45 24 4d a8 47 58 bc 9c |S.2%.)Z^E$M.GX..| +00000190 6f f3 61 a9 ca e0 ad 32 88 04 1a da 83 ff fd 31 |o.a....2.......1| +000001a0 84 65 9e 33 bb 79 d4 71 55 52 bc 57 fd 2e d5 98 |.e.3.y.qUR.W....| +000001b0 46 b9 dc 74 58 7c c9 25 44 3c 07 97 5d bc 65 b5 |F..tX|.%D<..].e.| +000001c0 b5 46 50 fa 52 f9 45 d7 0f f5 d2 4e 16 03 03 00 |.FP.R.E....N....| +000001d0 48 0f 00 00 44 08 07 00 40 e2 1c ab 11 6c 52 e6 |H...D...@....lR.| +000001e0 e8 7f 67 f0 6e 6a e4 a8 4f 25 89 31 d7 f8 dd 6f |..g.nj..O%.1...o| +000001f0 fd c7 84 e9 59 6b 77 b6 3b fb bc b3 d6 a7 96 4c |....Ykw.;......L| +00000200 2f 54 d2 cf 6b 06 5f a5 69 b6 85 0e a9 a2 90 aa |/T..k._.i.......| +00000210 c4 b2 89 17 b3 c7 b9 73 00 14 03 03 00 01 01 16 |.......s........| +00000220 03 03 00 40 45 8d 48 5b 23 74 21 05 ae 22 ce c0 |...@E.H[#t!.."..| +00000230 8a 05 9a 15 7e fb 61 73 dd 45 fd d0 97 a4 ca f5 |....~.as.E......| +00000240 84 f0 01 c4 e4 44 78 c2 14 4f b6 27 0f e8 5a 9d |.....Dx..O.'..Z.| +00000250 69 7c 9b c4 c5 a3 4d 42 bf 2b 89 c6 a3 c2 ca 7a |i|....MB.+.....z| +00000260 d3 6c 5e 51 |.l^Q| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 d4 e6 b8 6f 53 |..............oS| -00000020 6a d9 37 2b a4 95 9f 04 e5 99 2f f9 9a 16 fd a7 |j.7+....../.....| -00000030 2d 39 d9 aa 7c 26 9e 44 4b 7f 8f d5 c6 24 4d ac |-9..|&.DK....$M.| -00000040 13 ca 8a 45 1e 66 dc 9a bf 76 22 17 03 03 00 40 |...E.f...v"....@| +00000010 00 00 00 00 00 00 00 00 00 00 00 d0 d7 ea c0 57 |...............W| +00000020 b8 c4 0e ad 2b ba 7e f7 40 0e 92 42 0b c1 55 38 |....+.~.@..B..U8| +00000030 89 ac d8 9f 46 96 89 c8 a0 06 e7 84 ac 42 6f a8 |....F........Bo.| +00000040 e2 67 49 fe 5b 2f 66 3e 47 c3 14 17 03 03 00 40 |.gI.[/f>G......@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 3f 5c 60 f8 22 7b aa 82 38 c4 4a 2e 07 50 cb 6c |?\`."{..8.J..P.l| -00000070 3f 6f a9 39 bf 21 ce 7a 30 72 03 90 ec bc 9c 18 |?o.9.!.z0r......| -00000080 1f a9 7f 82 3a d9 46 d9 d8 b8 77 65 e8 b3 e7 f5 |....:.F...we....| +00000060 95 78 c4 75 cf 05 a9 ce aa 85 0b 8e 4e fc 4b dc |.x.u........N.K.| +00000070 59 70 3e 68 85 68 97 9a eb 22 22 3a 8c 61 91 a4 |Yp>h.h..."":.a..| +00000080 89 06 bd 9e fc 8d 1d 4b ed fe 4b d6 e7 0a 6e 2b |.......K..K...n+| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 6d 29 d4 87 0a b4 1d b4 9d f4 12 |.....m).........| -000000b0 bc 3d a3 1b 79 21 85 0d e7 10 64 92 40 39 05 99 |.=..y!....d.@9..| -000000c0 c8 a7 dd ef 0e |.....| +000000a0 00 00 00 00 00 92 d4 46 1f 6b d5 63 a7 95 0d c2 |.......F.k.c....| +000000b0 2f a9 a2 5f 0d 70 8f a5 31 e3 5c 1d fa ac f6 2e |/.._.p..1.\.....| +000000c0 02 6d e8 9f 95 |.m...| diff --git a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven index cc6450a4ce8..585e6af6579 100644 --- a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven +++ b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 6d 01 00 00 69 03 03 e9 31 0f d0 25 |....m...i...1..%| -00000010 ef 25 a7 1a 9b 8c 4b a3 ca 2b a6 54 89 1c e1 68 |.%....K..+.T...h| -00000020 6f b2 b2 60 6f 8a dc 87 24 8c 7b 00 00 04 00 2f |o..`o...$.{..../| +00000000 16 03 01 00 6d 01 00 00 69 03 03 0e c0 95 b1 0b |....m...i.......| +00000010 7b b5 57 cc 04 e7 03 d0 66 8d ee 9d da 65 dc 74 |{.W.....f....e.t| +00000020 0d de 11 47 38 cd 19 12 f4 06 17 00 00 04 00 2f |...G8........../| 00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| 00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| 00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| @@ -49,10 +49,10 @@ 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 23 0d 00 00 |.\!.;.......#...| -000002a0 1f 02 01 40 00 18 08 04 04 03 08 07 08 05 08 06 |...@............| -000002b0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 00 |................| -000002c0 16 03 03 00 04 0e 00 00 00 |.........| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 1f 0d 00 00 |.\!.;...........| +000002a0 1b 02 01 40 00 14 08 04 04 03 08 07 08 05 08 06 |...@............| +000002b0 04 01 05 01 06 01 05 03 06 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| 00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| @@ -86,40 +86,40 @@ 000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| 000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| 000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| -00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 29 51 da |.5...........)Q.| -00000210 8e 5c 3e fb 44 8a 0f 97 42 23 8b e2 73 cc e2 90 |.\>.D...B#..s...| -00000220 11 c4 98 01 e9 60 96 9e a9 96 30 c5 95 f8 56 0e |.....`....0...V.| -00000230 4a 2e 77 e7 7e 23 b7 49 31 c4 87 c5 69 c6 ca 6f |J.w.~#.I1...i..o| -00000240 ea 53 41 b4 2e 1e f6 0b 33 f5 e1 40 69 c0 91 6f |.SA.....3..@i..o| -00000250 88 c1 68 c8 18 99 6e fe b3 5f 9b ee f1 4a 76 41 |..h...n.._...JvA| -00000260 1f d1 05 f5 39 76 61 e6 a6 ea 75 0e 50 32 a1 19 |....9va...u.P2..| -00000270 20 6a 4c 5d 62 6e 2a 6e af f9 9c 38 b6 3a bc 86 | jL]bn*n...8.:..| -00000280 eb ac 6d d3 b5 48 30 11 4d 98 2e 61 34 16 03 03 |..m..H0.M..a4...| -00000290 00 88 0f 00 00 84 08 04 00 80 82 ed 3f da b5 50 |............?..P| -000002a0 d2 50 51 14 cf ee f7 b9 7b a9 0c 77 2f 88 42 0a |.PQ.....{..w/.B.| -000002b0 34 a9 5d e7 32 26 3a 28 87 49 fb c4 83 31 68 c6 |4.].2&:(.I...1h.| -000002c0 0d 32 d4 31 0a d1 d6 1e 6f 7f 89 93 bf b7 7c c7 |.2.1....o.....|.| -000002d0 95 f8 c3 69 d8 58 4e e4 76 07 36 84 b7 c3 e7 22 |...i.XN.v.6...."| -000002e0 01 4c 59 ae 89 95 bb e0 07 e0 31 6a e2 95 4c d4 |.LY.......1j..L.| -000002f0 01 54 9d 27 82 60 31 13 39 07 47 c2 0c 08 5c d4 |.T.'.`1.9.G...\.| -00000300 03 5a 6f d7 89 a0 67 5e 2d a0 11 03 bf 0e 35 d8 |.Zo...g^-.....5.| -00000310 d0 78 2f 1e d8 15 47 ce c9 d3 14 03 03 00 01 01 |.x/...G.........| -00000320 16 03 03 00 40 d0 0a 0e 93 dd 9a 51 4f a9 7f 5f |....@......QO.._| -00000330 93 a6 60 a6 f2 10 f1 bd bd ae 13 5d 11 b7 0d 1a |..`........]....| -00000340 3d 1e f3 0c b7 53 7c 10 ed fa 8c d7 3f 20 ec f2 |=....S|.....? ..| -00000350 7d e9 15 87 3d d3 05 21 3a bc a5 54 fa 40 3b 53 |}...=..!:..T.@;S| -00000360 41 7c ea c6 28 |A|..(| +00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 cc d2 66 |.5.............f| +00000210 37 df f1 5d cb 6f 1d 6b 64 ea 62 45 97 dd 47 f8 |7..].o.kd.bE..G.| +00000220 e5 a0 f6 84 46 9b 6c 5b c9 79 60 07 b0 d1 5a e6 |....F.l[.y`...Z.| +00000230 5c 1a 43 b1 04 9f f2 3d 7a 09 da e0 45 ea 30 8a |\.C....=z...E.0.| +00000240 5c 08 07 67 17 2e 55 f5 0a 13 96 5c 92 e5 61 66 |\..g..U....\..af| +00000250 92 fe c6 44 9c 4f 62 54 10 12 df f7 e4 11 74 f6 |...D.ObT......t.| +00000260 35 81 bb 55 4f ce 43 dc 7f 4d bc 4f 8b 0c ef 13 |5..UO.C..M.O....| +00000270 43 8a e5 80 dc 38 3e 8a f5 7b 5c 5d 1c 76 10 06 |C....8>..{\].v..| +00000280 3d c5 05 5b cb 9a 17 20 13 29 a5 36 5d 16 03 03 |=..[... .).6]...| +00000290 00 88 0f 00 00 84 08 04 00 80 a7 7f 2c 3b d1 82 |............,;..| +000002a0 8a 17 50 2a f6 c4 ac ce 47 1b 25 23 4b 0c d0 17 |..P*....G.%#K...| +000002b0 89 18 98 a6 e4 b8 51 70 6a 59 72 1a aa 68 e8 25 |......QpjYr..h.%| +000002c0 f5 4d 72 66 be bb 25 61 9b 36 e0 24 a5 34 e4 36 |.Mrf..%a.6.$.4.6| +000002d0 23 0a 36 a8 81 f4 19 62 98 2b af 1b f5 c4 55 d2 |#.6....b.+....U.| +000002e0 d5 65 58 b8 31 21 f4 fe ce 44 cc ea 77 8e 1d f7 |.eX.1!...D..w...| +000002f0 bc a4 4c e5 cc 90 10 f3 a0 8d 10 72 08 d4 50 1c |..L........r..P.| +00000300 88 82 a7 61 da cb 35 ba 26 3c 18 11 6c 14 d6 1a |...a..5.&<..l...| +00000310 7f 65 3d 2c 74 f0 92 a3 aa fd 14 03 03 00 01 01 |.e=,t...........| +00000320 16 03 03 00 40 f3 3a f0 23 48 35 41 7f d0 ed 22 |....@.:.#H5A..."| +00000330 5b 1a 47 71 60 08 b0 6b cd 32 56 c0 d0 05 90 b3 |[.Gq`..k.2V.....| +00000340 0b 35 3c 03 49 ec 06 5d b4 ce 1d 10 4e bc 75 bf |.5<.I..]....N.u.| +00000350 23 3b f1 d6 8f f6 f0 70 b6 94 8f 51 fd 4f 47 0b |#;.....p...Q.OG.| +00000360 e1 c9 ad c8 14 |.....| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 a8 8e 30 08 f0 |.............0..| -00000020 87 7b 13 31 99 6d 7e 9a 9b 03 d3 6f 84 d8 d9 31 |.{.1.m~....o...1| -00000030 2b d2 aa d4 0e ae 6e 72 03 ac e7 7e 5c 22 cc ac |+.....nr...~\"..| -00000040 33 b5 df 04 b2 4a 2b 6f bb a1 6f 17 03 03 00 40 |3....J+o..o....@| +00000010 00 00 00 00 00 00 00 00 00 00 00 6e d3 79 f1 02 |...........n.y..| +00000020 4d 8e ad 3b 33 5a 92 10 55 79 94 b7 43 ed 08 c1 |M..;3Z..Uy..C...| +00000030 e1 5f 04 c6 01 82 ce 96 70 c7 97 8d cc 0a ca d3 |._......p.......| +00000040 46 d4 2f 9f b8 78 57 27 ee 14 aa 17 03 03 00 40 |F./..xW'.......@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 50 9c 81 04 9b 1d 61 8a 30 9c 18 68 c7 e1 c9 f3 |P.....a.0..h....| -00000070 70 f0 1b b6 4a dd fc c7 e3 e3 20 e2 4d 6f 9f bf |p...J..... .Mo..| -00000080 17 b0 5e 5b 45 73 29 1e d4 30 b4 03 ca 8e 69 63 |..^[Es)..0....ic| +00000060 ed 9f 38 f6 99 84 f5 cf 5e ee 27 64 f7 29 3c 18 |..8.....^.'d.)<.| +00000070 a0 55 23 b7 db 4a 6d 2d 80 c9 75 a5 a3 1f 38 24 |.U#..Jm-..u...8$| +00000080 0a 99 18 0d 0b 5d 7d 03 f7 8d d2 55 fd 98 7f 69 |.....]}....U...i| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 28 ca 6a 4c 1b 3c 11 61 ce b2 58 |.....(.jL.<.a..X| -000000b0 94 e7 e4 7d c5 ce 51 03 c4 ae b5 4c 33 0b 3c 95 |...}..Q....L3.<.| -000000c0 ec b1 65 ea da |..e..| +000000a0 00 00 00 00 00 aa 43 ca 95 7d 1a 47 d5 0b 0e c7 |......C..}.G....| +000000b0 cc 61 3d 43 5b 69 05 a1 39 eb 03 52 41 05 54 e9 |.a=C[i..9..RA.T.| +000000c0 5d b6 ca 56 2c |]..V,| diff --git a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given index 875fe1becb1..10949e5e3ba 100644 --- a/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given +++ b/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 6d 01 00 00 69 03 03 dc f3 c6 52 a4 |....m...i.....R.| -00000010 9a 9c 53 e0 5a 3c cc 4c 4f 09 32 7f f1 7c 86 6b |..S.Z<.LO.2..|.k| -00000020 75 59 68 a5 81 72 45 46 fb 94 a8 00 00 04 00 2f |uYh..rEF......./| +00000000 16 03 01 00 6d 01 00 00 69 03 03 c2 c7 15 c0 0f |....m...i.......| +00000010 0d fc 44 60 25 22 6c 4a ec f1 b0 66 5d c4 f3 bc |..D`%"lJ...f]...| +00000020 fe da b2 9a af 24 04 b7 bb 74 79 00 00 04 00 2f |.....$...ty..../| 00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| 00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| 00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| @@ -49,10 +49,10 @@ 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 23 0d 00 00 |.\!.;.......#...| -000002a0 1f 02 01 40 00 18 08 04 04 03 08 07 08 05 08 06 |...@............| -000002b0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 00 |................| -000002c0 16 03 03 00 04 0e 00 00 00 |.........| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 1f 0d 00 00 |.\!.;...........| +000002a0 1b 02 01 40 00 14 08 04 04 03 08 07 08 05 08 06 |...@............| +000002b0 04 01 05 01 06 01 05 03 06 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| 00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| @@ -86,40 +86,40 @@ 000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| 000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| 000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| -00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 b5 77 6b |.5............wk| -00000210 fa 10 fb df 48 8f e7 51 b4 cb 14 c5 48 bd 63 d6 |....H..Q....H.c.| -00000220 0e 19 d0 81 a8 5a d7 b5 43 84 35 85 37 b7 8d 2e |.....Z..C.5.7...| -00000230 c7 c8 70 4c f4 45 bf be 17 86 e7 40 1d 6f 88 2a |..pL.E.....@.o.*| -00000240 91 b5 aa aa 34 f7 9a f3 96 e4 dd 51 15 88 be f1 |....4......Q....| -00000250 80 a9 6f 94 ed c7 5d 28 66 b4 37 e8 22 4f 42 c3 |..o...](f.7."OB.| -00000260 b5 f0 2f dd 57 dc 8d e5 5a c0 9d fa ce 3c 7a 2d |../.W...Z....>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 a2 b0 ad 7e 71 |..............~q| -00000020 0c 2c db df 4c b1 4f 19 e6 00 4f 11 ff 5e 4a c5 |.,..L.O...O..^J.| -00000030 c2 9d 8c 6c 03 50 12 3d 81 ec 44 5a 75 ba 2d 48 |...l.P.=..DZu.-H| -00000040 7a 74 c3 a3 68 5a 26 ee 7e f5 a2 17 03 03 00 40 |zt..hZ&.~......@| +00000010 00 00 00 00 00 00 00 00 00 00 00 0c 22 6e 84 b2 |............"n..| +00000020 a1 f9 18 62 3a 86 16 7e e6 17 3b 8e e5 88 b8 8e |...b:..~..;.....| +00000030 3c c5 08 11 8e 0a df df d4 69 bc 01 7d c8 63 33 |<........i..}.c3| +00000040 b5 15 bf 03 5e df 50 29 c5 c4 c2 17 03 03 00 40 |....^.P).......@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 ad 1b 16 8e 39 99 64 7c c5 49 24 83 c4 4e f6 86 |....9.d|.I$..N..| -00000070 6b 5d 68 ae f4 0b 58 23 83 eb ab 01 52 4d 07 a1 |k]h...X#....RM..| -00000080 59 00 e8 dc a5 a1 6f 76 e2 e9 f2 e1 21 58 6b a0 |Y.....ov....!Xk.| +00000060 45 76 91 63 fa 48 9b c9 47 6a f6 7b fa 72 ab 78 |Ev.c.H..Gj.{.r.x| +00000070 4f cb c4 bb 68 78 7c 71 13 f9 47 32 33 59 d4 16 |O...hx|q..G23Y..| +00000080 83 fa 8e db 37 b6 cb d5 a1 1a e5 21 1b 50 a6 d3 |....7......!.P..| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 3c 6e a7 81 36 d0 8c 99 d8 f3 55 |.....>> Flow 1 (client to server) -00000000 16 03 01 00 6d 01 00 00 69 03 03 ac ea d9 49 98 |....m...i.....I.| -00000010 9a 0c 7c 86 64 7c 73 72 6d 79 3f 7b e9 11 8b 1d |..|.d|srmy?{....| -00000020 79 95 f5 f5 23 9f b2 f1 9c f4 b5 00 00 04 00 2f |y...#........../| +00000000 16 03 01 00 6d 01 00 00 69 03 03 f2 1b 6e dc ce |....m...i....n..| +00000010 fe af a8 4b 44 88 5f ba eb c5 d7 92 7e 69 d7 19 |...KD._.....~i..| +00000020 b3 32 d3 99 e6 be 1f 4f 94 04 e6 00 00 04 00 2f |.2.....O......./| 00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| 00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| 00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| @@ -49,37 +49,37 @@ 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 23 0d 00 00 |.\!.;.......#...| -000002a0 1f 02 01 40 00 18 08 04 04 03 08 07 08 05 08 06 |...@............| -000002b0 04 01 05 01 06 01 05 03 06 03 02 01 02 03 00 00 |................| -000002c0 16 03 03 00 04 0e 00 00 00 |.........| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 1f 0d 00 00 |.\!.;...........| +000002a0 1b 02 01 40 00 14 08 04 04 03 08 07 08 05 08 06 |...@............| +000002b0 04 01 05 01 06 01 05 03 06 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 00 07 0b 00 00 03 00 00 00 16 03 03 00 |................| -00000010 86 10 00 00 82 00 80 2e 37 44 fb d7 1d 2f 3d a5 |........7D.../=.| -00000020 1b 43 cf f4 1c cf 9d 95 fa be 9f 9d 96 8a 27 5d |.C............']| -00000030 7b be 19 10 bd 5e 9a 3e 49 49 d2 af 85 07 70 f8 |{....^.>II....p.| -00000040 c8 4f 69 02 ff 4e 9d ee f4 0d 4d 54 a1 aa 61 a3 |.Oi..N....MT..a.| -00000050 e0 cc db a7 2c 46 80 6e eb 10 fb cd 2e 3b c5 50 |....,F.n.....;.P| -00000060 2b a5 d9 a0 bf 01 d2 f8 d8 51 2b ad 40 6f c6 6f |+........Q+.@o.o| -00000070 0e 30 53 27 73 89 b7 1b c1 28 ff ff 18 4c fa 6f |.0S's....(...L.o| -00000080 fa 5f 16 b3 38 36 9f f4 07 74 ca bb bb c2 3f aa |._..86...t....?.| -00000090 0d e7 42 24 fb f8 4c 14 03 03 00 01 01 16 03 03 |..B$..L.........| -000000a0 00 40 19 02 9e 3a ce b9 38 40 ce d6 3b 87 b2 f6 |.@...:..8@..;...| -000000b0 1b 7d ee 76 62 f8 6e 04 80 8f cb 1b f7 1e 1d a6 |.}.vb.n.........| -000000c0 50 8a 59 b1 ad 7d c5 9d 2f 2d 14 56 2e e5 3b b3 |P.Y..}../-.V..;.| -000000d0 db da 7e 37 10 97 71 91 d3 7b 93 f6 64 a4 d7 8b |..~7..q..{..d...| -000000e0 d2 f0 |..| +00000010 86 10 00 00 82 00 80 36 1c ba 9d 08 27 52 8b f7 |.......6....'R..| +00000020 24 d9 e6 18 d7 21 75 1d 76 e0 13 a0 35 d5 08 7d |$....!u.v...5..}| +00000030 c1 8e 3f b2 aa 10 b4 f9 d4 77 e6 cd b3 92 94 0e |..?......w......| +00000040 7a c9 0b 5f e2 34 88 ad fc 02 1b 84 10 ff e8 2a |z.._.4.........*| +00000050 dd 2d 82 5c bb ca 15 f8 73 74 ad dd 9f 9d e7 38 |.-.\....st.....8| +00000060 7c cd 74 8e 37 0f 87 62 cf 30 68 8a e2 15 9d d2 ||.t.7..b.0h.....| +00000070 43 4b e3 29 69 e4 db 94 9b 5a 7c c6 9b e8 7d 26 |CK.)i....Z|...}&| +00000080 4b a8 4a 28 c1 47 cf 15 7b 22 a2 1d 6b ac 16 e4 |K.J(.G..{"..k...| +00000090 e1 62 6e be 9a 05 67 14 03 03 00 01 01 16 03 03 |.bn...g.........| +000000a0 00 40 98 4e 3d 6c 72 d8 7f 81 b6 b8 ed 32 2e 98 |.@.N=lr......2..| +000000b0 8d fc c1 1d 56 97 82 ef 3f 7c 86 79 e3 27 06 ed |....V...?|.y.'..| +000000c0 87 c4 28 2d 6b f1 b1 88 d0 67 34 64 ba e1 d9 34 |..(-k....g4d...4| +000000d0 a4 2c ff e0 b2 38 21 5d 04 64 99 a4 34 62 aa 81 |.,...8!].d..4b..| +000000e0 cf 21 |.!| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 46 c8 31 06 11 |...........F.1..| -00000020 01 8e df b0 e7 cc 16 d3 97 2e a2 68 e7 a4 d1 0f |...........h....| -00000030 91 71 dd ba db 97 20 45 60 c2 47 c7 ee 56 c4 68 |.q.... E`.G..V.h| -00000040 a4 b1 05 09 e2 68 4d 54 fa ff 01 17 03 03 00 40 |.....hMT.......@| +00000010 00 00 00 00 00 00 00 00 00 00 00 66 31 30 4e 0f |...........f10N.| +00000020 de bd de 72 65 0c 74 ab 64 d8 59 47 fc 6b ad d8 |...re.t.d.YG.k..| +00000030 73 24 da 77 62 ba 0a 8c 69 d3 c4 6f 89 ef 5b 92 |s$.wb...i..o..[.| +00000040 d3 ca 3b e8 67 2b 7c bf 39 7c 8b 17 03 03 00 40 |..;.g+|.9|.....@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 79 bf ad 63 e3 11 2b d0 41 0e 24 85 92 c4 9b b5 |y..c..+.A.$.....| -00000070 b2 d3 2e fc aa 46 84 85 a7 37 90 fc f0 2b 5a 7e |.....F...7...+Z~| -00000080 28 9f 2e 57 1d 8f c3 ca eb 40 32 79 af 4b b8 28 |(..W.....@2y.K.(| +00000060 5c a8 b1 1c 7e e1 76 b8 d0 0c 4d 3d 3f 36 a8 26 |\...~.v...M=?6.&| +00000070 66 00 dd 47 3c ae 1c 8b 6f b0 6b 80 75 c4 0b 7e |f..G<...o.k.u..~| +00000080 ee fb 8c fe 2f 2f 65 1b 9b e1 72 a9 ac 8f cf da |....//e...r.....| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 8b 6c 27 b8 ff f9 ea ca 68 75 54 |......l'.....huT| -000000b0 bf bf a7 f4 b1 58 a5 b3 31 01 4d c7 85 58 31 d4 |.....X..1.M..X1.| -000000c0 e7 da 7e 77 68 |..~wh| +000000a0 00 00 00 00 00 9d 96 95 12 3b 42 41 a8 30 b2 8c |.........;BA.0..| +000000b0 3d 18 f6 27 b7 77 30 d9 29 0c 68 ec 2b 09 26 91 |=..'.w0.).h.+.&.| +000000c0 23 0c e2 10 07 |#....| diff --git a/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES index 697b8102dd3..f0d266bdc7a 100644 --- a/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 85 01 00 00 81 03 03 83 21 a6 e4 ea |............!...| -00000010 e9 7b 3a 7c 72 28 ee 68 c5 c7 fa f1 98 ed 4a be |.{:|r(.h......J.| -00000020 b8 42 13 fb d3 ab 63 16 d2 74 c8 00 00 04 c0 0a |.B....c..t......| +00000000 16 03 01 00 85 01 00 00 81 03 03 19 8a e1 c7 50 |...............P| +00000010 ba 63 15 9b d5 85 f1 8c 55 43 d3 ce 9c d6 35 20 |.c......UC....5 | +00000020 f3 49 3d 55 a5 11 57 6d db 42 1d 00 00 04 c0 0a |.I=U..Wm.B......| 00000030 00 ff 01 00 00 54 00 0b 00 04 03 00 01 02 00 0a |.....T..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 00000050 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 03 |.........0......| @@ -46,39 +46,39 @@ 00000220 c1 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 |.3.......7z..z..| 00000230 2e dd d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 |....i..|V..1x+..| 00000240 78 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 |x.....N6$1{j.9..| -00000250 07 8f 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 |..*............ | +00000250 07 8f 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 |..*............ | 00000260 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 |/.}.G.bC.(.._.).| 00000270 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |0.........._X.;t| -00000280 04 03 00 8b 30 81 88 02 42 00 b9 39 44 59 12 77 |....0...B..9DY.w| -00000290 8d e2 79 25 01 d1 6a 05 3d 53 ea f3 91 d6 c5 09 |..y%..j.=S......| -000002a0 24 bd 0c ad 24 cc 1c a7 fb 03 eb 0a 0d f4 30 96 |$...$.........0.| -000002b0 8d 28 a1 b3 64 ba 30 27 95 29 23 22 91 62 c3 1f |.(..d.0'.)#".b..| -000002c0 51 aa c8 be 17 85 31 8e f5 40 3e 02 42 00 ee a1 |Q.....1..@>.B...| -000002d0 64 14 a1 52 b3 e5 54 c9 24 53 94 5a 43 d8 4f 79 |d..R..T.$S.ZC.Oy| -000002e0 69 4b a8 51 ee de b3 b0 f7 1a 57 a3 28 72 d2 13 |iK.Q......W.(r..| -000002f0 a6 d3 17 0b c4 45 34 7f 10 3b 81 cb 0c 8d 51 b6 |.....E4..;....Q.| -00000300 0b 86 21 d0 ee 1d 7e 73 6b ea 77 8c 66 dc 65 16 |..!...~sk.w.f.e.| -00000310 03 03 00 04 0e 00 00 00 |........| +00000280 04 03 00 8a 30 81 87 02 42 01 f2 09 77 4a e7 f5 |....0...B...wJ..| +00000290 a8 35 3b dd 9d 62 5a 07 97 1e 76 93 b6 07 21 3e |.5;..bZ...v...!>| +000002a0 c8 fd 99 35 50 8a 8b ad e5 de 03 07 c8 5e fe 03 |...5P........^..| +000002b0 c1 99 04 ad 53 b6 76 67 eb 04 99 54 11 4d 4d e9 |....S.vg...T.MM.| +000002c0 74 3f 89 6e d9 c8 02 98 c5 3c cf 02 41 4e 64 21 |t?.n.....<..ANd!| +000002d0 1a 01 5f 2e 89 17 cc 65 33 d0 59 ed 17 59 c4 43 |.._....e3.Y..Y.C| +000002e0 0a fc 68 30 9c e2 c3 86 fb 2a c1 4a ae 32 ef 1d |..h0.....*.J.2..| +000002f0 06 27 36 7d d5 cd 68 23 4c e9 7e 64 b8 eb 42 05 |.'6}..h#L.~d..B.| +00000300 ef 83 36 b2 9e a7 ae 1a cd b0 3a 17 3a 46 16 03 |..6.......:.:F..| +00000310 03 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 ed 3e ba a7 43 53 |....%...! .>..CS| -00000010 5e e4 60 aa 31 3f e1 69 60 32 25 3d fd 8b 32 da |^.`.1?.i`2%=..2.| -00000020 f2 c5 db c7 02 e6 4d d0 de 15 14 03 03 00 01 01 |......M.........| -00000030 16 03 03 00 40 ee 28 f2 27 82 24 9d 17 d1 48 7a |....@.(.'.$...Hz| -00000040 74 2d dd 16 18 b7 70 97 2f 2b 91 47 eb c2 1d ae |t-....p./+.G....| -00000050 3f 48 52 cd ff e7 9e 0b 35 ad 1f 60 5e 07 b1 5e |?HR.....5..`^..^| -00000060 1c ba 6a 85 bb 6b 30 94 41 8a 59 81 cf 37 5f 26 |..j..k0.A.Y..7_&| -00000070 b1 52 36 5f df |.R6_.| +00000000 16 03 03 00 25 10 00 00 21 20 73 43 c2 08 92 f5 |....%...! sC....| +00000010 db bf 2f 8a eb 49 55 f7 5d 6b 80 64 f7 d9 75 1f |../..IU.]k.d..u.| +00000020 67 f6 35 21 3c 95 3f 1c 04 1a 14 03 03 00 01 01 |g.5!<.?.........| +00000030 16 03 03 00 40 59 bb 5a 5d 76 73 a5 30 0e 29 d3 |....@Y.Z]vs.0.).| +00000040 17 d8 2f 30 e6 ed 02 c6 83 12 44 42 d8 79 86 e0 |../0......DB.y..| +00000050 78 7b 43 8d 5b 7c 85 42 fb 7c 67 b0 d0 71 03 0e |x{C.[|.B.|g..q..| +00000060 d0 6b b6 06 f1 16 72 c0 16 66 cf 53 df ae 62 3b |.k....r..f.S..b;| +00000070 f3 57 52 4d 08 |.WRM.| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 f5 05 5a a6 22 |.............Z."| -00000020 90 4e 8d d9 f1 55 c4 78 f2 ec 9d 97 cd fe af ae |.N...U.x........| -00000030 b7 62 00 67 2e b2 d9 1e 0c a3 c8 6a bf d2 3c 42 |.b.g.......j..u......| +00000080 cd 14 5b 4b 0a 7b a2 e6 54 b3 bd 3c f0 eb ca 78 |..[K.{..T..<...x| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 13 3e 42 a5 61 84 ae 49 8b b9 91 |......>B.a..I...| -000000b0 c2 a3 76 74 1e 4f 53 0a fc 71 de 0d d2 44 c8 ac |..vt.OS..q...D..| -000000c0 2e 09 27 e6 ad |..'..| +000000a0 00 00 00 00 00 e6 4b 35 cc 69 58 89 49 67 99 f4 |......K5.iX.Ig..| +000000b0 c2 14 2a bb e7 21 2b fe fe b5 60 ae b2 2a 96 15 |..*..!+...`..*..| +000000c0 e0 65 d2 54 0b |.e.T.| diff --git a/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial b/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial index ff8d63568d7..a670f05d58c 100644 --- a/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial +++ b/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 89 01 00 00 85 03 03 ad 13 87 9e b3 |................| -00000010 c7 71 bb bf be e3 b9 80 3f 17 bf 41 37 95 22 e6 |.q......?..A7.".| -00000020 f2 98 a9 15 62 1d 65 06 69 ea 53 00 00 04 c0 14 |....b.e.i.S.....| +00000000 16 03 01 00 89 01 00 00 85 03 03 ba bc af a2 f7 |................| +00000010 a2 a0 19 81 f0 3b c0 76 56 10 e6 95 ce ab 89 82 |.....;.vV.......| +00000020 d5 27 b3 78 69 f2 d3 5b 2d 97 77 00 00 04 c0 14 |.'.xi..[-.w.....| 00000030 00 ff 01 00 00 58 00 0b 00 04 03 00 01 02 00 0a |.....X..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..| @@ -54,43 +54,43 @@ 000002a0 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d 20 2f |.............. /| 000002b0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000002c0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 |.........._X.;t.| -000002d0 04 00 80 41 24 c2 f9 e8 40 21 47 3c ab 8e 99 5e |...A$...@!G<...^| -000002e0 0e 08 27 86 6c 29 ae 36 ed 21 18 23 67 cc f7 d5 |..'.l).6.!.#g...| -000002f0 3f e2 2c 48 2f 3d 47 e5 af d5 61 86 0f 91 69 30 |?.,H/=G...a...i0| -00000300 cf 84 56 f2 d3 c1 9a a3 a1 a2 c8 ef 4d 33 de 12 |..V.........M3..| -00000310 d6 46 55 5b c6 6a 65 a5 36 b5 51 5b db 04 25 aa |.FU[.je.6.Q[..%.| -00000320 1c af a0 b0 2d ee db 00 c5 ad 1b 94 d3 90 11 86 |....-...........| -00000330 10 83 35 41 65 9e a4 2c a9 ee 37 ac d4 cc 05 76 |..5Ae..,..7....v| -00000340 92 59 f9 51 68 79 6d 9e 5f eb 80 47 3a 7c e0 74 |.Y.Qhym._..G:|.t| -00000350 ac f5 36 16 03 03 00 04 0e 00 00 00 |..6.........| +000002d0 04 00 80 59 86 4b 13 6a 34 c5 bd 82 a9 ae d8 bf |...Y.K.j4.......| +000002e0 7b 9b f2 c2 0a aa 81 99 25 d8 14 68 32 49 00 ab |{.......%..h2I..| +000002f0 b0 18 4e 05 50 31 0e 25 f3 db 5f 93 45 13 a4 3e |..N.P1.%.._.E..>| +00000300 38 76 a1 0d d8 87 0f 85 81 0c af cb cd e8 43 cd |8v............C.| +00000310 67 01 f2 15 e0 7e 11 44 2a 8d ba 12 33 94 01 c9 |g....~.D*...3...| +00000320 81 bd 99 0d 9f 84 04 a0 7c 0f 24 dd 79 34 53 ba |........|.$.y4S.| +00000330 fa ae 32 16 0c 30 6c f0 76 5d 75 c1 ba d9 35 86 |..2..0l.v]u...5.| +00000340 b0 94 2f 1f 35 7f 1c 1f 92 10 c5 88 55 cc 2c 5b |../.5.......U.,[| +00000350 89 b3 58 16 03 03 00 04 0e 00 00 00 |..X.........| >>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 d2 ed 26 ce 1f 5d |....%...! ..&..]| -00000010 50 b8 f4 19 fc 63 e2 b6 3d 7d 39 54 c2 c1 61 a9 |P....c..=}9T..a.| -00000020 2a 82 d8 e3 a9 2f 22 8c b2 18 14 03 03 00 01 01 |*..../".........| -00000030 16 03 03 00 40 82 78 f0 1e e6 03 20 67 66 4e d6 |....@.x.... gfN.| -00000040 93 25 69 9e 38 c6 dd 17 92 02 18 7f 5f 9c 9c f0 |.%i.8......._...| -00000050 a3 f7 45 d3 ba 82 e3 01 38 e5 4f cf 8b 0e 77 6e |..E.....8.O...wn| -00000060 91 99 83 e0 f1 3d e8 a1 39 d4 ea b3 2e 1c 67 59 |.....=..9.....gY| -00000070 c5 5d 83 30 dc |.].0.| +00000000 16 03 03 00 25 10 00 00 21 20 7b e4 41 19 92 fc |....%...! {.A...| +00000010 73 0d 4b 88 2d bd e2 a1 f3 6a ad 5b 8c 10 9b 9e |s.K.-....j.[....| +00000020 46 7a c0 81 96 03 0b 4c 03 7d 14 03 03 00 01 01 |Fz.....L.}......| +00000030 16 03 03 00 40 e5 e4 11 bd 7c 54 b8 be 80 44 82 |....@....|T...D.| +00000040 03 22 51 7f f5 de 92 20 7d 34 b0 9a 7b 17 ce 12 |."Q.... }4..{...| +00000050 b4 75 44 9b 37 b1 cd 1f 0c f8 86 4c 75 d9 1e 75 |.uD.7......Lu..u| +00000060 d3 7e bf 6e 3e 9d be 3b c1 47 11 6d f1 09 10 2e |.~.n>..;.G.m....| +00000070 d0 0d cd 1f 26 |....&| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d 70 97 51 ed 14 ef 68 ca 42 c5 4c ff 6b a2 |o-p.Q...h.B.L.k.| -00000030 3e f9 07 a9 91 ad 0d c7 23 bd 7f 04 cf 4d a0 eb |>.......#....M..| -00000040 58 e0 e1 37 73 d3 cc 4b e2 7f 6d 3a 2e 47 b5 b4 |X..7s..K..m:.G..| -00000050 60 dd e6 9a ea 30 1e 6e 7a e7 8e 84 ca 49 38 16 |`....0.nz....I8.| -00000060 7e 51 5c e5 15 c0 58 7d a2 ba e2 ca 90 24 11 ea |~Q\...X}.....$..| -00000070 53 9c 7d cb 47 13 91 cf f6 05 f0 2f db 57 1a 40 |S.}.G....../.W.@| -00000080 57 b0 d4 97 8e 23 7e f5 14 03 03 00 01 01 16 03 |W....#~.........| -00000090 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| -000000a0 00 00 00 72 43 0e f2 f3 bb e8 6d 3b f2 ff 96 53 |...rC.....m;...S| -000000b0 12 36 07 e0 f0 17 35 e7 52 87 a3 12 7b 53 d4 83 |.6....5.R...{S..| -000000c0 cc d2 d3 06 4b e2 3a fc 38 4f a7 75 d8 3c 6a a4 |....K.:.8O.u..u.L| +00000040 72 93 e7 50 f9 17 7b 90 0d 70 e7 b8 5c 7b 93 81 |r..P..{..p..\{..| +00000050 66 e1 64 b0 a9 25 34 84 bc 49 42 f5 13 49 38 16 |f.d..%4..IB..I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 07 da 2f 56 e0 05 62 |~Q\...X}R../V..b| +00000070 16 1e 0c 62 76 cc b5 ff 25 a1 c3 2e 1f 28 71 29 |...bv...%....(q)| +00000080 9c d0 c1 0a 05 dd 22 57 7a 19 14 03 03 00 01 01 |......"Wz.......| +00000090 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +000000a0 00 00 00 00 00 9a 9d 01 bc db e5 21 c2 d2 f8 d8 |...........!....| +000000b0 b8 c1 86 87 fc b6 79 df 69 be d2 97 cd 69 76 9d |......y.i....iv.| +000000c0 04 95 7f d4 e8 c7 78 52 c0 d1 ac bc 55 08 57 a7 |......xR....U.W.| +000000d0 9c 28 d4 7b df 17 03 03 00 40 00 00 00 00 00 00 |.(.{.....@......| +000000e0 00 00 00 00 00 00 00 00 00 00 81 f0 80 62 50 04 |.............bP.| +000000f0 7f 86 ee f1 73 46 b0 c3 c1 0d 92 ab dd 4f b9 2a |....sF.......O.*| +00000100 58 4f 17 9f be 60 ff 8b 1a d6 e3 94 aa dc 8b 60 |XO...`.........`| +00000110 d8 2b 4c c8 5a 69 18 74 65 49 15 03 03 00 30 00 |.+L.Zi.teI....0.| +00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 |................| +00000130 36 4f 05 fe ab 47 92 6e 48 42 4f 06 c4 f3 e1 70 |6O...G.nHBO....p| +00000140 c6 66 00 1d aa 84 6b 2b d4 23 37 c9 42 fb 6d |.f....k+.#7.B.m| diff --git a/crypto/tls/testdata/Server-TLSv12-IssueTicket b/crypto/tls/testdata/Server-TLSv12-IssueTicket index ee293586102..b05669d073b 100644 --- a/crypto/tls/testdata/Server-TLSv12-IssueTicket +++ b/crypto/tls/testdata/Server-TLSv12-IssueTicket @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 71 01 00 00 6d 03 03 bf f8 80 5d 1b |....q...m.....].| -00000010 ea 95 cb 32 3b 8f ff 5e f9 4d 58 7d dc a4 50 cc |...2;..^.MX}..P.| -00000020 68 4d 40 98 11 af f3 e4 d7 31 43 00 00 04 00 2f |hM@......1C..../| +00000000 16 03 01 00 71 01 00 00 6d 03 03 ae 71 d4 07 74 |....q...m...q..t| +00000010 03 93 b0 1f 88 72 ef d2 54 61 44 34 5f 3f ea 16 |.....r..TaD4_?..| +00000020 32 41 11 a9 00 9b 59 ba 50 a8 ab 00 00 04 00 2f |2A....Y.P....../| 00000030 00 ff 01 00 00 40 00 23 00 00 00 16 00 00 00 17 |.....@.#........| 00000040 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| 00000050 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 |................| @@ -52,39 +52,39 @@ 00000290 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| 000002a0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) -00000000 16 03 03 00 86 10 00 00 82 00 80 35 d7 dd 48 68 |...........5..Hh| -00000010 17 8c 9b 02 75 0c 6b 76 17 0a e1 f8 06 c0 d7 1d |....u.kv........| -00000020 bf a5 97 d2 59 0f c9 90 4a f0 6f 40 dc e7 30 c4 |....Y...J.o@..0.| -00000030 75 ab 74 9c 32 48 a4 84 3c 40 a0 bd 03 aa 09 2b |u.t.2H..<@.....+| -00000040 b2 4c 80 82 17 b8 3d 27 16 9a b7 90 66 f2 10 4e |.L....='....f..N| -00000050 41 7e 78 24 de 27 91 f9 e9 bc bf 15 3a 35 1b ae |A~x$.'......:5..| -00000060 28 9e e1 09 f0 7a 4d 66 7e de d1 43 bf f5 e4 09 |(....zMf~..C....| -00000070 a7 21 cb 0e 1d 59 6d a0 a6 41 44 58 f4 ab ac 6a |.!...Ym..ADX...j| -00000080 98 db 25 e3 57 ee 94 87 85 51 ea 14 03 03 00 01 |..%.W....Q......| -00000090 01 16 03 03 00 40 c9 64 79 e7 15 1d 30 15 95 89 |.....@.dy...0...| -000000a0 b1 9b 12 42 69 4b 22 20 54 5a aa b6 71 02 1c 3f |...BiK" TZ..q..?| -000000b0 7c b5 66 07 b5 1f 55 96 3f ce 47 1f 66 52 d8 6b ||.f...U.?.G.fR.k| -000000c0 65 71 c0 4e 0b 7e 55 e0 f5 af 42 29 af 2b 1d 0e |eq.N.~U...B).+..| -000000d0 e6 96 cd 7b fc d3 |...{..| +00000000 16 03 03 00 86 10 00 00 82 00 80 1a 4a c4 37 68 |............J.7h| +00000010 6a c0 28 f1 ea ea 14 20 fe c3 b6 61 28 67 75 7b |j.(.... ...a(gu{| +00000020 74 e0 6b ab 2c dd c8 13 0a be d6 71 a1 13 96 5a |t.k.,......q...Z| +00000030 bf 89 2e 6e 6a 61 24 ca d4 88 3f f8 20 ed 20 1f |...nja$...?. . .| +00000040 0a 9c 11 9b 96 e1 cd d8 38 42 05 be b8 6e e5 fe |........8B...n..| +00000050 54 c8 93 b8 56 67 01 97 a0 bc 37 33 7c 40 f7 77 |T...Vg....73|@.w| +00000060 5d 8b 63 bc 3f 7b e3 e9 0a b0 13 06 12 6e 8e 1c |].c.?{.......n..| +00000070 7c e7 ed 99 6d c3 5a 93 92 d2 4a fe fa d9 10 1c ||...m.Z...J.....| +00000080 76 e2 9e d7 d4 cd c7 b9 7a 40 54 14 03 03 00 01 |v.......z@T.....| +00000090 01 16 03 03 00 40 ac 11 71 60 db b6 db b9 db fb |.....@..q`......| +000000a0 09 20 8d 00 e9 69 25 15 f9 14 8f 08 7a 6c 8c 29 |. ...i%.....zl.)| +000000b0 0d f4 9b d3 ca c8 c8 f3 11 0a 85 d6 c2 cc 60 a7 |..............`.| +000000c0 8c a3 32 06 08 15 bd 84 a0 4f 17 b9 6b 9b 6a 7c |..2......O..k.j|| +000000d0 23 9d 74 22 7f fd |#.t"..| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d b0 ac 51 ed 14 ef 68 ca 42 c5 4c 85 f6 26 |o-..Q...h.B.L..&| -00000030 0d a4 ad a8 f5 14 64 4f b9 c3 fb 1e 55 c1 1f c7 |......dO....U...| -00000040 31 57 72 68 db 03 37 a8 c9 07 f4 ca 62 6c 5c f3 |1Wrh..7.....bl\.| -00000050 8b 5a 3d 76 dd 63 ea 68 61 6b a1 2d 95 49 38 16 |.Z=v.c.hak.-.I8.| -00000060 7e 51 5c e5 15 c0 58 7d c5 67 4a 6f 64 b6 79 1a |~Q\...X}.gJod.y.| -00000070 41 9b b1 33 15 38 74 92 5c a5 48 c3 f2 94 bb 33 |A..3.8t.\.H....3| -00000080 ec af cf d7 e7 c9 3e 35 14 03 03 00 01 01 16 03 |......>5........| -00000090 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| -000000a0 00 00 00 19 51 7c 1c a3 80 34 e1 81 30 3f f9 a4 |....Q|...4..0?..| -000000b0 a0 97 97 fd 94 fb ab e8 80 48 25 7b 83 ca 38 61 |.........H%{..8a| -000000c0 34 95 d0 52 6f 09 ad 4f 74 35 c5 3d e8 bb aa 5d |4..Ro..Ot5.=...]| -000000d0 d0 fc 85 17 03 03 00 40 00 00 00 00 00 00 00 00 |.......@........| -000000e0 00 00 00 00 00 00 00 00 e7 19 f9 fd 10 7c 17 04 |.............|..| -000000f0 2d ce 5f a6 41 33 3d 05 b0 29 91 ff a0 a5 76 52 |-._.A3=..)....vR| -00000100 e1 b9 ba 6a ca d3 79 60 11 ac 43 b5 30 f7 15 dc |...j..y`..C.0...| -00000110 6f b1 d2 b2 00 85 43 40 15 03 03 00 30 00 00 00 |o.....C@....0...| -00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 19 99 8a |................| -00000130 4c 18 e0 03 cc 27 7a be 2c e5 d2 16 95 f6 a4 6e |L....'z.,......n| -00000140 11 d3 1d f4 01 52 2b fc 98 04 b1 0b 31 |.....R+.....1| +00000020 6f 2d b0 ac 51 ed 14 ef 68 ca 42 c5 4c 52 2e 96 |o-..Q...h.B.LR..| +00000030 6b e5 cc b4 0c ee 82 5b c1 57 52 8e dd 26 c8 58 |k......[.WR..&.X| +00000040 27 01 5f ec 58 a0 5c ad 74 e8 82 b7 ab 86 71 25 |'._.X.\.t.....q%| +00000050 aa ed ec ef 69 5f 7e 1d f2 58 30 13 75 49 38 16 |....i_~..X0.uI8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 1a 43 47 27 99 9d 0f |~Q\...X}R.CG'...| +00000070 e0 4c f4 3b e0 b0 76 ae e6 5d a4 a0 34 38 8b b0 |.L.;..v..]..48..| +00000080 3a ba 26 90 a3 dd c2 dc 26 98 14 03 03 00 01 01 |:.&.....&.......| +00000090 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +000000a0 00 00 00 00 00 55 e7 9a 32 83 32 d1 01 6e 0e 5a |.....U..2.2..n.Z| +000000b0 dd 72 c5 f9 90 24 6b da 73 d9 ed 39 b8 d5 f6 93 |.r...$k.s..9....| +000000c0 e0 f0 3e 20 db d0 0c 8a b0 10 78 1e 08 fb 47 44 |..> ......x...GD| +000000d0 27 74 30 c4 73 17 03 03 00 40 00 00 00 00 00 00 |'t0.s....@......| +000000e0 00 00 00 00 00 00 00 00 00 00 0a ae 7e 4e c4 37 |............~N.7| +000000f0 65 b9 bf 66 a5 c5 5d a2 bc 76 7a db c9 cd 0b 85 |e..f..]..vz.....| +00000100 de 86 e4 94 2c f2 87 1f 7a 4b 31 b7 4d 77 18 8a |....,...zK1.Mw..| +00000110 6d 5e af d0 eb 87 bf d9 c5 e3 15 03 03 00 30 00 |m^............0.| +00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9f |................| +00000130 8a 39 93 10 94 78 d1 dc 81 07 b6 1a 1a c3 96 c1 |.9...x..........| +00000140 28 d3 30 eb 3d 1a d3 d6 d8 3a d2 33 ec ed 6c |(.0.=....:.3..l| diff --git a/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable index 20ce3c3cc8c..a86d19c35a8 100644 --- a/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable +++ b/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 71 01 00 00 6d 03 03 a1 ba 69 29 39 |....q...m....i)9| -00000010 b5 fc c7 90 90 54 35 be 5a ad 4a e2 b2 3d b9 01 |.....T5.Z.J..=..| -00000020 f0 48 fd 77 b5 9e bc 89 f5 d4 df 00 00 04 00 2f |.H.w.........../| +00000000 16 03 01 00 71 01 00 00 6d 03 03 9d 49 68 d2 e5 |....q...m...Ih..| +00000010 4a 77 05 39 fb b6 c2 e8 79 b8 cd e7 42 dd f5 29 |Jw.9....y...B..)| +00000020 4f 24 92 27 bf 94 95 89 8a 0c 5f 00 00 04 00 2f |O$.'......_..../| 00000030 00 ff 01 00 00 40 00 23 00 00 00 16 00 00 00 17 |.....@.#........| 00000040 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| 00000050 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 |................| @@ -52,39 +52,39 @@ 00000290 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| 000002a0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) -00000000 16 03 03 00 86 10 00 00 82 00 80 cc 4e 62 e0 bf |............Nb..| -00000010 21 65 dc f2 57 fb fe 6e e4 cc de b4 1f aa af 52 |!e..W..n.......R| -00000020 a4 e0 0e 1b fa 8b 23 4b d9 e2 4b 62 6a 26 80 f7 |......#K..Kbj&..| -00000030 15 82 ba 44 4a 18 b8 97 ca a1 79 4b 11 59 90 7d |...DJ.....yK.Y.}| -00000040 ea 89 7c f9 6b 5f 29 c7 ca 32 bf 3b 53 b2 bb bb |..|.k_)..2.;S...| -00000050 77 0a 5c 1f c2 d8 20 cf 59 19 4e a0 ff ef ca ca |w.\... .Y.N.....| -00000060 25 39 ac c7 64 b9 e8 68 09 f2 49 96 8e 49 c7 4c |%9..d..h..I..I.L| -00000070 cd ff 28 6f d8 0d d3 7a ae 7a 51 9e 04 70 8a 59 |..(o...z.zQ..p.Y| -00000080 8c 05 61 c9 2b bd e1 05 5a 12 63 14 03 03 00 01 |..a.+...Z.c.....| -00000090 01 16 03 03 00 40 ac 30 bb 83 2f e2 a1 98 a3 c5 |.....@.0../.....| -000000a0 9c e3 55 36 70 a0 10 fc 53 7e 2d ae f1 02 d7 04 |..U6p...S~-.....| -000000b0 1f 4e 5d ed 33 29 99 04 54 8e 51 74 d5 2a 73 21 |.N].3)..T.Qt.*s!| -000000c0 4f bf 8b 0c 04 b2 f2 d4 3e a7 f6 ee 8b fb 3a 0b |O.......>.....:.| -000000d0 86 27 7c a7 bb 32 |.'|..2| +00000000 16 03 03 00 86 10 00 00 82 00 80 2b 09 f3 6c 39 |...........+..l9| +00000010 25 51 ab 73 c9 5d e4 de bb b3 7d 8e 40 96 df f9 |%Q.s.]....}.@...| +00000020 28 24 82 47 21 40 2d cb bd 7d a5 2a 89 91 7d e0 |($.G!@-..}.*..}.| +00000030 4c 92 ca 8f 2c 2d be 93 d1 a2 00 ef 3a 4b 6b de |L...,-......:Kk.| +00000040 e9 ab 38 0b 19 21 35 5d fb 06 b1 1f dd 75 db d6 |..8..!5].....u..| +00000050 6b 16 7e 1e 32 ef 58 11 78 ef 6e 7f cc 1f cd 8e |k.~.2.X.x.n.....| +00000060 57 01 96 eb 06 bf 09 10 99 ed 3c 35 94 9f 03 66 |W.........<5...f| +00000070 a4 e1 96 22 eb f5 cd 28 1f 4e 2c b9 2c 48 29 bf |..."...(.N,.,H).| +00000080 b3 43 c1 b9 f0 aa 2b 29 47 a4 38 14 03 03 00 01 |.C....+)G.8.....| +00000090 01 16 03 03 00 40 75 ac e5 40 a2 19 82 90 ef 25 |.....@u..@.....%| +000000a0 9c 3b c2 95 fb 58 b9 c8 72 2c b3 94 d5 23 e9 f6 |.;...X..r,...#..| +000000b0 0d 03 2e 24 54 73 c3 5b 0d 84 2d 5b 12 f6 f9 5a |...$Ts.[..-[...Z| +000000c0 59 6d ea 80 5e b6 ab 34 5f 57 98 fb 2c c8 e2 d0 |Ym..^..4_W..,...| +000000d0 3e fb 32 4c b1 93 |>.2L..| >>> Flow 4 (server to client) -00000000 16 03 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 |..............y.| +00000000 16 03 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 |..............{.| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000020 6f 2d b0 ac 51 ed 14 ef 68 ca 42 c5 4c fa 53 68 |o-..Q...h.B.L.Sh| -00000030 d9 20 e9 d9 c1 9c 90 3b f2 e6 57 af 04 e5 db 6b |. .....;..W....k| -00000040 36 0b b5 b8 e2 a5 a4 bf 52 31 80 32 b9 da d9 32 |6.......R1.2...2| -00000050 36 e7 31 d3 22 78 12 ae 7a 80 ac fa 6d 49 38 16 |6.1."x..z...mI8.| -00000060 7e 51 5c e5 15 c0 58 7d d6 77 d5 17 1b d9 a8 74 |~Q\...X}.w.....t| -00000070 be 93 25 54 84 a7 1a 93 1f 20 a4 49 eb 26 e7 8e |..%T..... .I.&..| -00000080 d3 0f cf 9c 75 cc 6f 36 14 03 03 00 01 01 16 03 |....u.o6........| -00000090 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| -000000a0 00 00 00 eb f1 52 79 ff b8 6c 9c 23 f3 22 bc 96 |.....Ry..l.#."..| -000000b0 2a bc e7 73 05 32 4b 2e e4 5e 31 97 62 86 cc 12 |*..s.2K..^1.b...| -000000c0 ae 22 77 92 37 5d 82 41 57 48 aa f4 0a f3 94 30 |."w.7].AWH.....0| -000000d0 5d 06 7b 17 03 03 00 40 00 00 00 00 00 00 00 00 |].{....@........| -000000e0 00 00 00 00 00 00 00 00 8f 8d a7 06 a7 d6 52 5a |..............RZ| -000000f0 b9 66 5e ef e3 8d 1d 91 d0 6d 30 29 92 4e 6a 81 |.f^......m0).Nj.| -00000100 f4 77 97 06 de a8 c8 d1 4c 6b 15 07 1f 9b 59 6d |.w......Lk....Ym| -00000110 cb 4f 23 20 58 aa 22 21 15 03 03 00 30 00 00 00 |.O# X."!....0...| -00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 06 55 3d |..............U=| -00000130 42 f5 12 b2 66 aa af 00 91 5e b8 31 ae 19 0e 35 |B...f....^.1...5| -00000140 a2 d7 a6 e7 0c 3c 2b 95 62 69 d7 a0 81 |.....<+.bi...| +00000020 6f 2d b0 ac 51 ed 14 ef 68 ca 42 c5 4c ba fa 12 |o-..Q...h.B.L...| +00000030 47 15 bc 82 f4 35 e2 0f 0f 2b d3 02 30 a7 c3 bb |G....5...+..0...| +00000040 48 06 b7 80 c5 21 70 95 bf fd e5 fa d8 aa ee 9c |H....!p.........| +00000050 d6 10 79 3b f9 e6 9e 21 21 bd e9 50 ba 49 38 16 |..y;...!!..P.I8.| +00000060 7e 51 5c e5 15 c0 58 7d 52 1a 2e ee ae e1 df 6c |~Q\...X}R......l| +00000070 d2 82 e8 11 4b d9 3a b4 ed 46 56 6a 8e cd 4b 70 |....K.:..FVj..Kp| +00000080 37 5c 82 fc ef d7 ff 38 65 e6 14 03 03 00 01 01 |7\.....8e.......| +00000090 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +000000a0 00 00 00 00 00 8a 27 b1 df e3 23 8d 5e a8 06 e0 |......'...#.^...| +000000b0 3b 70 3a 8a f2 36 09 e5 0b 91 03 0c ab c7 6b 2c |;p:..6........k,| +000000c0 ee 8d fd b3 d1 3b 0b d6 08 45 af 26 40 ad c7 fd |.....;...E.&@...| +000000d0 8f fa fa f6 c0 17 03 03 00 40 00 00 00 00 00 00 |.........@......| +000000e0 00 00 00 00 00 00 00 00 00 00 c0 62 b3 b3 3d 17 |...........b..=.| +000000f0 5d 7f a6 7d 7b eb ea 35 f5 46 3c 69 94 a0 37 ca |]..}{..5.F>> Flow 1 (client to server) -00000000 16 03 01 01 0a 01 00 01 06 03 03 2d b6 ca ea 39 |...........-...9| -00000010 59 17 86 df 90 2f 73 e0 a0 5c 6e 28 09 78 69 d6 |Y..../s..\n(.xi.| -00000020 30 06 b7 7b 17 a9 79 30 2a d8 57 20 c5 5c ed 86 |0..{..y0*.W .\..| -00000030 15 f4 3b c8 d2 5f 7a 80 2a 6a cd 40 c2 da 6f a8 |..;.._z.*j.@..o.| -00000040 cd d7 e7 bf 48 bd fb a1 e9 4b 9b a9 00 04 00 2f |....H....K...../| -00000050 00 ff 01 00 00 b9 00 23 00 79 00 00 00 00 00 00 |.......#.y......| +00000000 16 03 01 01 0c 01 00 01 08 03 03 a6 8e 75 2d a5 |.............u-.| +00000010 52 ef 15 c3 e3 42 53 88 55 21 76 a9 8c 44 e8 df |R....BS.U!v..D..| +00000020 f4 1c 40 08 1a 35 46 4b 6d 4f ff 20 e3 91 5e 82 |..@..5FKmO. ..^.| +00000030 58 5e 5a 37 a7 16 d8 fe 96 0e 2c 45 13 ac 4f 30 |X^Z7......,E..O0| +00000040 96 a3 17 a2 16 49 00 d6 8e b6 6a 4d 00 04 00 2f |.....I....jM.../| +00000050 00 ff 01 00 00 bb 00 23 00 7b 00 00 00 00 00 00 |.......#.{......| 00000060 00 00 00 00 00 00 00 00 00 00 94 6f 2d b0 ac 51 |...........o-..Q| -00000070 ed 14 ef 68 ca 42 c5 4c 85 f6 26 0d a4 ad a8 f5 |...h.B.L..&.....| -00000080 14 64 4f b9 c3 fb 1e 55 c1 1f c7 31 57 72 68 db |.dO....U...1Wrh.| -00000090 03 37 a8 c9 07 f4 ca 62 6c 5c f3 8b 5a 3d 76 dd |.7.....bl\..Z=v.| -000000a0 63 ea 68 61 6b a1 2d 95 49 38 16 7e 51 5c e5 15 |c.hak.-.I8.~Q\..| -000000b0 c0 58 7d c5 67 4a 6f 64 b6 79 1a 41 9b b1 33 15 |.X}.gJod.y.A..3.| -000000c0 38 74 92 5c a5 48 c3 f2 94 bb 33 ec af cf d7 e7 |8t.\.H....3.....| -000000d0 c9 3e 35 00 16 00 00 00 17 00 00 00 0d 00 30 00 |.>5...........0.| -000000e0 2e 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 |................| -000000f0 0b 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 |................| -00000100 03 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |...............| +00000070 ed 14 ef 68 ca 42 c5 4c 52 2e 96 6b e5 cc b4 0c |...h.B.LR..k....| +00000080 ee 82 5b c1 57 52 8e dd 26 c8 58 27 01 5f ec 58 |..[.WR..&.X'._.X| +00000090 a0 5c ad 74 e8 82 b7 ab 86 71 25 aa ed ec ef 69 |.\.t.....q%....i| +000000a0 5f 7e 1d f2 58 30 13 75 49 38 16 7e 51 5c e5 15 |_~..X0.uI8.~Q\..| +000000b0 c0 58 7d 52 1a 43 47 27 99 9d 0f e0 4c f4 3b e0 |.X}R.CG'....L.;.| +000000c0 b0 76 ae e6 5d a4 a0 34 38 8b b0 3a ba 26 90 a3 |.v..]..48..:.&..| +000000d0 dd c2 dc 26 98 00 16 00 00 00 17 00 00 00 0d 00 |...&............| +000000e0 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 08 |0...............| +000000f0 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 03 |................| +00000100 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 06 |................| +00000110 02 |.| >>> Flow 2 (server to client) 00000000 16 03 03 00 59 02 00 00 55 03 03 00 00 00 00 00 |....Y...U.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 44 4f 57 4e 47 52 44 01 20 c5 5c ed 86 |...DOWNGRD. .\..| -00000030 15 f4 3b c8 d2 5f 7a 80 2a 6a cd 40 c2 da 6f a8 |..;.._z.*j.@..o.| -00000040 cd d7 e7 bf 48 bd fb a1 e9 4b 9b a9 00 2f 00 00 |....H....K.../..| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 20 e3 91 5e 82 |...DOWNGRD. ..^.| +00000030 58 5e 5a 37 a7 16 d8 fe 96 0e 2c 45 13 ac 4f 30 |X^Z7......,E..O0| +00000040 96 a3 17 a2 16 49 00 d6 8e b6 6a 4d 00 2f 00 00 |.....I....jM./..| 00000050 0d 00 23 00 00 ff 01 00 01 00 00 17 00 00 16 03 |..#.............| -00000060 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 00 00 |............y...| +00000060 03 00 85 04 00 00 81 00 00 00 00 00 7b 00 00 00 |............{...| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 94 6f 2d |..............o-| -00000080 b0 ac 51 ed 14 ef 68 ca 42 c5 4c 85 f6 26 0d a4 |..Q...h.B.L..&..| -00000090 ad a8 f5 14 64 4f b9 c3 fb 1e 55 c1 1f c7 31 57 |....dO....U...1W| -000000a0 72 68 db 03 37 a8 c9 07 f4 ca 62 6c 5c f3 8b 5a |rh..7.....bl\..Z| -000000b0 3d 76 dd 63 ea 68 61 6b a1 2d 95 49 38 16 7e 51 |=v.c.hak.-.I8.~Q| -000000c0 5c e5 15 c0 58 7d c5 67 4a 6f 64 b6 79 1a 41 9b |\...X}.gJod.y.A.| -000000d0 b1 33 15 38 74 92 5c a5 48 c3 f2 94 bb 33 ec af |.3.8t.\.H....3..| -000000e0 cf d7 e7 c9 3e 35 14 03 03 00 01 01 16 03 03 00 |....>5..........| -000000f0 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@...............| -00000100 00 47 68 3a 66 5b d6 ed b7 60 a9 fb e8 37 d6 9d |.Gh:f[...`...7..| -00000110 a6 b9 4d d5 f3 9f 0f c6 3c 21 6e d5 80 08 a8 34 |..M.......k| -00000130 40 |@| +00000080 b0 ac 51 ed 14 ef 68 ca 42 c5 4c 52 2e 96 6b e5 |..Q...h.B.LR..k.| +00000090 cc b4 0c ee 82 5b c1 57 52 8e dd 26 c8 58 27 01 |.....[.WR..&.X'.| +000000a0 5f ec 58 a0 5c ad 74 e8 82 b7 ab 86 71 25 aa ed |_.X.\.t.....q%..| +000000b0 ec ef 69 5f 7e 1d f2 58 30 13 75 49 38 16 7e 51 |..i_~..X0.uI8.~Q| +000000c0 5c e5 15 c0 58 7d 52 1a 43 47 27 99 9d 0f e0 4c |\...X}R.CG'....L| +000000d0 f4 3b e0 b0 76 ae e6 5d a4 a0 34 38 8b b0 3a ba |.;..v..]..48..:.| +000000e0 26 90 a3 dd c2 dc 26 98 14 03 03 00 01 01 16 03 |&.....&.........| +000000f0 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| +00000100 00 00 00 fb 6c 2b 7d a1 a6 a1 aa 6f 38 3f e2 8a |....l+}....o8?..| +00000110 09 da 48 94 ce 2a 70 70 8c d3 5d bd 8c e5 74 fc |..H..*pp..]...t.| +00000120 91 05 dc 9e f1 2d a6 db 3c d6 06 50 b7 9d 4d 8b |.....-..<..P..M.| +00000130 b7 d4 06 |...| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 16 03 03 00 40 46 34 b3 97 54 |..........@F4..T| -00000010 20 5b 95 f3 22 f8 a1 89 c8 95 93 ba 7b a4 a8 8f | [..".......{...| -00000020 46 a8 d6 c1 b3 ac f0 e0 49 3d 8d e4 1c ac b8 a4 |F.......I=......| -00000030 01 21 5e d8 f0 f5 10 10 f7 de 8b 33 9d 94 cf f6 |.!^........3....| -00000040 f2 9b 39 22 5c e6 c0 5e b4 1d cd |..9"\..^...| +00000000 14 03 03 00 01 01 16 03 03 00 40 b0 47 45 3b 24 |..........@.GE;$| +00000010 ae 4b 98 d6 cc 37 28 ab 3b ea 7e 6b bc 1f ed a5 |.K...7(.;.~k....| +00000020 bb 67 e2 5e 72 bf d5 28 90 dc 1b 98 87 2c 49 c6 |.g.^r..(.....,I.| +00000030 90 73 45 3f 1b 8c a2 c5 50 84 48 09 41 e1 ea 52 |.sE?....P.H.A..R| +00000040 9e 17 ad 8f d6 cd cd 16 7a 90 64 |........z.d| >>> Flow 4 (server to client) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 5c bc 45 06 2e d3 7b 30 99 a6 af |.....\.E...{0...| -00000020 64 0e 63 93 73 6f 0a e7 a4 1d ac 94 25 11 a5 63 |d.c.so......%..c| -00000030 8d b2 44 aa 98 44 f8 b5 51 ea 2c fb 26 99 f6 a4 |..D..D..Q.,.&...| -00000040 2c f8 15 c3 90 15 03 03 00 30 00 00 00 00 00 00 |,........0......| -00000050 00 00 00 00 00 00 00 00 00 00 c6 58 8e 7c 97 de |...........X.|..| -00000060 3b b8 39 cd 7b 1d 67 77 27 da 93 39 52 a7 81 9b |;.9.{.gw'..9R...| -00000070 ab 5a bc e9 00 1a 64 3a ca f5 |.Z....d:..| +00000010 00 00 00 00 00 a6 e7 61 5a 2b 01 ce 94 48 d2 09 |.......aZ+...H..| +00000020 13 a5 90 a8 58 47 8d fd ab 69 85 fa 42 00 3d 99 |....XG...i..B.=.| +00000030 d1 fd 16 88 0b 2a 43 92 54 e7 55 2e dd 70 86 e1 |.....*C.T.U..p..| +00000040 f1 c5 5c c8 1e 15 03 03 00 30 00 00 00 00 00 00 |..\......0......| +00000050 00 00 00 00 00 00 00 00 00 00 ba 42 cf 74 9f 00 |...........B.t..| +00000060 4a 76 d5 cf 48 23 ed 4a 42 62 be 1a 35 d2 8c d2 |Jv..H#.JBb..5...| +00000070 ee 86 2f 3a f5 4d 96 64 f7 b8 |../:.M.d..| diff --git a/crypto/tls/testdata/Server-TLSv12-SNI b/crypto/tls/testdata/Server-TLSv12-SNI index c3dc1b6e52d..b7889def656 100644 --- a/crypto/tls/testdata/Server-TLSv12-SNI +++ b/crypto/tls/testdata/Server-TLSv12-SNI @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 81 01 00 00 7d 03 03 cc a1 7b c4 56 |........}....{.V| -00000010 9f 65 31 01 b0 23 09 18 10 50 7c 1e 14 7b b5 dd |.e1..#...P|..{..| -00000020 d4 70 07 3e 0b 19 19 31 6b f7 4d 00 00 04 00 2f |.p.>...1k.M..../| +00000000 16 03 01 00 81 01 00 00 7d 03 03 5b 8e 50 b3 0e |........}..[.P..| +00000010 1f d7 4f a4 0f 53 de 37 1a c6 86 2f 01 c0 0b 15 |..O..S.7.../....| +00000020 cf a9 f4 f5 30 c0 aa 7e cc 5b 4e 00 00 04 00 2f |....0..~.[N..../| 00000030 00 ff 01 00 00 50 00 00 00 10 00 0e 00 00 0b 73 |.....P.........s| 00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 16 00 00 00 17 |nitest.com......| 00000050 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| @@ -9,75 +9,75 @@ 00000070 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 02 |................| 00000080 04 02 05 02 06 02 |......| >>> Flow 2 (server to client) -00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000000 16 03 03 00 39 02 00 00 35 03 03 00 00 00 00 00 |....9...5.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| -00000030 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| -00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| -00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| -00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| -00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| -00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| -00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| -000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| -000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| -000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| -000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| -000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| -000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| -00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| -00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| -00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| -00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| -00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| -00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| -00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| -00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| -00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| -00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| -000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| -000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| -000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| -000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| -000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| -000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| -00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| -00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| -00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| -00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| -00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | -00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| -00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| -00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| -00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........| -000002a0 00 |.| +00000030 0d ff 01 00 01 00 00 17 00 00 00 00 00 00 16 03 |................| +00000040 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000050 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000060 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000070 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +00000080 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +00000090 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000a0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000b0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000c0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000d0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +000000e0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +000000f0 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000100 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000110 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000120 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000130 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000140 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000150 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000160 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000170 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +00000180 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +00000190 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001a0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001b0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001c0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001d0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +000001e0 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +000001f0 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000200 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000210 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000220 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000230 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000240 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000250 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000260 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000270 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +00000280 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +00000290 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002a0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) -00000000 16 03 03 00 86 10 00 00 82 00 80 04 36 4c 25 96 |............6L%.| -00000010 b0 1a 33 80 88 98 4f 2a c8 93 24 81 0a 78 6c 85 |..3...O*..$..xl.| -00000020 06 4d f1 cf 25 18 e0 f0 61 50 c5 45 c1 24 1b b3 |.M..%...aP.E.$..| -00000030 d6 3c d3 49 a6 40 81 2c bb ef 49 76 c0 10 4c ad |.<.I.@.,..Iv..L.| -00000040 2e 7d 4d f4 0b 96 bc 1c eb 3d 1d 7d 18 25 34 14 |.}M......=.}.%4.| -00000050 ed 76 f2 a1 17 aa 87 1b ef ff 11 93 a7 44 0c 33 |.v...........D.3| -00000060 86 27 38 3d 5d 3f bb f1 8d a9 f5 44 28 d1 28 41 |.'8=]?.....D(.(A| -00000070 bb b7 9a fb 83 81 91 92 4e 7d 71 55 43 ed 42 12 |........N}qUC.B.| -00000080 86 5f de 02 13 1f c4 63 08 87 db 14 03 03 00 01 |._.....c........| -00000090 01 16 03 03 00 40 32 01 5f a2 e1 08 cf 6b ce 11 |.....@2._....k..| -000000a0 db 82 94 c5 f1 12 9a ac 68 dc f9 c8 2c 00 a5 dd |........h...,...| -000000b0 6b 49 c8 8b b7 9f e3 90 27 a5 c2 45 fc 75 e5 ac |kI......'..E.u..| -000000c0 77 0c 80 bd 43 41 d4 00 c0 fb 8d 08 a6 f4 f7 63 |w...CA.........c| -000000d0 07 01 09 06 e5 fc |......| +00000000 16 03 03 00 86 10 00 00 82 00 80 25 3d 8b d1 c0 |...........%=...| +00000010 ef 86 34 20 a5 4b 4b 94 d9 c8 04 ff 02 13 24 57 |..4 .KK.......$W| +00000020 21 7f f1 c1 06 0b ea 1f b1 06 e8 fa 9b 5c 34 96 |!............\4.| +00000030 23 2a 4b ef cb d7 47 75 05 74 f3 7f ed fb 28 6a |#*K...Gu.t....(j| +00000040 cd b8 16 12 96 4b b7 cf 0c c3 b0 93 c3 ea b0 78 |.....K.........x| +00000050 65 93 9d 6d a9 d5 b7 ed be 8b 3a f6 12 bb 5d ae |e..m......:...].| +00000060 2b 17 2f 62 ca 21 68 7d 12 52 e3 2c cc 32 4b 94 |+./b.!h}.R.,.2K.| +00000070 4b 1d 73 9a 2e 60 60 da e6 32 dd d3 4d 39 69 c8 |K.s..``..2..M9i.| +00000080 b7 9d 8a 1d d8 57 90 13 4c 2a a9 14 03 03 00 01 |.....W..L*......| +00000090 01 16 03 03 00 40 c4 71 f6 06 63 08 15 02 63 0a |.....@.q..c...c.| +000000a0 59 40 55 52 28 17 3f 16 c8 48 93 af 80 87 e6 a8 |Y@UR(.?..H......| +000000b0 37 a4 4f 20 f0 37 88 5b 55 f3 32 60 c7 c4 1d ce |7.O .7.[U.2`....| +000000c0 b2 b8 d1 2d 8b fb a6 87 39 c8 75 31 22 77 33 82 |...-....9.u1"w3.| +000000d0 64 0f f2 10 9d ee |d.....| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 6d 31 fe 01 3d |...........m1..=| -00000020 2a c3 97 67 9f 08 f8 c9 ce 57 5c 4a e6 da 17 f2 |*..g.....W\J....| -00000030 f8 47 2b d9 9d 7e af 59 b8 a9 23 9d 7e d5 ed 77 |.G+..~.Y..#.~..w| -00000040 3b cd d4 b7 76 5b 6f 6d 09 bd 0c 17 03 03 00 40 |;...v[om.......@| +00000010 00 00 00 00 00 00 00 00 00 00 00 f2 12 bf 38 31 |..............81| +00000020 ee c9 9a 6a 8d fb 1c 53 41 f1 06 3a 44 9c 31 31 |...j...SA..:D.11| +00000030 25 7b 28 08 f5 3a 85 84 f1 83 61 9b 8c e3 cf 79 |%{(..:....a....y| +00000040 3a c2 ce e2 9c b8 52 ca 4f 5c b1 17 03 03 00 40 |:.....R.O\.....@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 d2 8c 47 46 36 47 fa d8 f8 1c b4 fc f6 fd fb 4b |..GF6G.........K| -00000070 79 e1 a3 39 df ac 6c 94 61 dd 20 1a e7 c0 4c 9c |y..9..l.a. ...L.| -00000080 45 69 69 cf 73 cb b1 6c fc 71 49 de 41 ca 4d 4f |Eii.s..l.qI.A.MO| +00000060 56 57 a0 ee c3 3e 4a 13 70 d5 05 2a 7d ed 49 81 |VW...>J.p..*}.I.| +00000070 52 37 e0 dc bd d0 e3 de f8 8e 18 a2 8b f8 62 71 |R7............bq| +00000080 7f a9 35 50 91 81 6f 33 63 e3 c5 ec cf fa 1b 05 |..5P..o3c.......| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 d1 66 64 ce 59 eb 23 13 e9 92 28 |......fd.Y.#...(| -000000b0 a4 2a 7a b0 e1 79 ce 92 34 77 6e b3 8d d3 bb e6 |.*z..y..4wn.....| -000000c0 ad 90 e8 a2 1a |.....| +000000a0 00 00 00 00 00 e5 05 33 38 e8 33 35 a3 f0 aa f8 |.......38.35....| +000000b0 8c b7 c5 2b 8c d0 9e 40 57 c5 c9 52 61 ae 5e c7 |...+...@W..Ra.^.| +000000c0 50 f1 5a 28 50 |P.Z(P| diff --git a/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate b/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate index 474ab1ab10a..b7756a3d10a 100644 --- a/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate +++ b/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 81 01 00 00 7d 03 03 02 34 82 a7 1a |........}...4...| -00000010 fe 81 b0 1c 2e df cc 04 2d f7 22 39 34 95 c7 c1 |........-."94...| -00000020 b2 92 a2 d2 aa ca 57 0f 9c be b4 00 00 04 00 2f |......W......../| +00000000 16 03 01 00 81 01 00 00 7d 03 03 37 94 a0 f3 65 |........}..7...e| +00000010 7b 07 88 ab 9f 29 dd 9a 56 a8 27 84 75 29 4f 24 |{....)..V.'.u)O$| +00000020 ce a2 ef 9b 34 ff 69 06 4c c8 e5 00 00 04 00 2f |....4.i.L....../| 00000030 00 ff 01 00 00 50 00 00 00 10 00 0e 00 00 0b 73 |.....P.........s| 00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 16 00 00 00 17 |nitest.com......| 00000050 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| @@ -9,75 +9,75 @@ 00000070 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 02 |................| 00000080 04 02 05 02 06 02 |......| >>> Flow 2 (server to client) -00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000000 16 03 03 00 39 02 00 00 35 03 03 00 00 00 00 00 |....9...5.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| -00000030 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| -00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| -00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| -00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| -00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| -00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| -00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| -000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| -000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| -000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| -000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| -000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| -000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| -00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| -00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| -00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| -00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| -00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| -00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| -00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| -00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| -00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| -00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| -000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| -000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| -000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| -000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| -000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| -000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| -00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| -00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| -00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| -00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| -00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | -00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| -00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| -00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| -00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........| -000002a0 00 |.| +00000030 0d ff 01 00 01 00 00 17 00 00 00 00 00 00 16 03 |................| +00000040 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000050 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000060 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000070 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +00000080 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +00000090 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000a0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000b0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000c0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000d0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +000000e0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +000000f0 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000100 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000110 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000120 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000130 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000140 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000150 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000160 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000170 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +00000180 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +00000190 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001a0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001b0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001c0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001d0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +000001e0 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +000001f0 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000200 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000210 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000220 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000230 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000240 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000250 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000260 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000270 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +00000280 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +00000290 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002a0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) -00000000 16 03 03 00 86 10 00 00 82 00 80 d9 90 3c 11 be |.............<..| -00000010 f3 48 de f0 8f 9e 12 ca e0 ab 86 e0 7e e7 8b ea |.H..........~...| -00000020 1a 76 3e 65 8d 7a d6 1c 72 2a f7 1e aa 0a 12 8f |.v>e.z..r*......| -00000030 54 ac 33 95 9d 00 a9 a6 94 54 7b 6a d9 e3 f4 67 |T.3......T{j...g| -00000040 a6 d3 b1 c1 5d 86 51 aa 63 67 6b 6e cb 3b 5e 59 |....].Q.cgkn.;^Y| -00000050 02 c2 57 fd 37 39 1b 73 9a 61 b0 78 de e8 cc f8 |..W.79.s.a.x....| -00000060 b3 01 11 e5 e9 31 85 4d fe 60 d4 12 70 71 64 45 |.....1.M.`..pqdE| -00000070 e8 7d fb be 5b 82 c0 c4 e1 57 09 2c f2 d7 a3 79 |.}..[....W.,...y| -00000080 1c 40 08 e1 e6 cd e2 3e e7 55 da 14 03 03 00 01 |.@.....>.U......| -00000090 01 16 03 03 00 40 29 9e b7 cf 5e 7c e9 40 91 5f |.....@)...^|.@._| -000000a0 b6 12 d4 42 ec 6a bc 03 d9 fa e4 d8 bf c7 2c c5 |...B.j........,.| -000000b0 52 74 17 77 b1 aa 13 87 f0 81 da 0d ca 7f d9 ca |Rt.w............| -000000c0 18 46 55 62 3f 90 21 60 fa 85 8c 80 6b 23 45 e7 |.FUb?.!`....k#E.| -000000d0 0b 6e 8c e2 c3 f6 |.n....| +00000000 16 03 03 00 86 10 00 00 82 00 80 1f fb a2 ec cf |................| +00000010 39 a3 cd db ee 86 8e 22 91 e1 47 5b ac 3b c0 f6 |9......"..G[.;..| +00000020 37 0f d0 b6 19 c5 a4 4c 1a 8f 8b 67 8a 20 0e 06 |7......L...g. ..| +00000030 6a 25 d9 13 58 37 cb dc 9b 3a 0f 9d 12 02 45 3f |j%..X7...:....E?| +00000040 2d 51 f5 cd 9f 45 be 5e f9 af 13 53 c2 15 a6 ca |-Q...E.^...S....| +00000050 8a cb 27 e0 d1 23 7a 19 06 26 d6 86 de 76 e7 9c |..'..#z..&...v..| +00000060 eb f8 15 1d 85 3f be 38 c4 bc 48 c3 74 d4 10 9b |.....?.8..H.t...| +00000070 9e 97 4c 1c 56 18 9d 65 1c be 33 3c 4c 90 e0 e4 |..L.V..e..3.]| +000000b0 3e c1 c2 0c c5 20 eb 76 e1 14 16 95 9c 56 10 67 |>.... .v.....V.g| +000000c0 02 61 2f a6 af 01 b3 64 73 4a 80 53 4a 94 b3 a0 |.a/....dsJ.SJ...| +000000d0 ee b5 95 b6 6a 20 |....j | >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 ee 8d 0f cd 15 |................| -00000020 db b4 cd 25 27 b6 7e 9b 82 91 2f 01 e1 4f f9 0c |...%'.~.../..O..| -00000030 68 4c bf 26 2b 4b 49 f5 0a 67 8a 4f 12 35 37 75 |hL.&+KI..g.O.57u| -00000040 16 fe cc 26 35 66 60 8c ed 42 40 17 03 03 00 40 |...&5f`..B@....@| +00000010 00 00 00 00 00 00 00 00 00 00 00 0e 0d f6 1c 84 |................| +00000020 d7 1a 4b 45 a1 9b e1 22 78 31 89 0c 4d f3 5b b8 |..KE..."x1..M.[.| +00000030 41 22 4f b2 aa 99 9e 5c 7c ff 2d ca db 32 01 eb |A"O....\|.-..2..| +00000040 55 2a f4 66 58 4a c2 fd 9f e5 7e 17 03 03 00 40 |U*.fXJ....~....@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 f5 7a ee 53 aa 85 bb 81 c4 57 68 12 f1 40 4c 20 |.z.S.....Wh..@L | -00000070 2a ff fc 6c dd 73 65 fc 41 e6 5b 96 6b 35 2f 8a |*..l.se.A.[.k5/.| -00000080 62 49 4a da f4 df 93 a0 ab e1 12 4d 8d 34 2c 6a |bIJ........M.4,j| +00000060 6c e0 c3 a0 c9 bd 12 83 58 56 e7 f4 cf 31 8f 1d |l.......XV...1..| +00000070 02 17 ce 2b 24 1c 2f 04 11 cc b2 15 38 62 d2 7d |...+$./.....8b.}| +00000080 1b 75 bc 20 a6 3a 65 48 2e 47 14 17 19 51 aa 71 |.u. .:eH.G...Q.q| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 1c 08 e5 52 29 79 d6 15 07 10 44 |........R)y....D| -000000b0 95 07 07 cb 3b 2b 37 2f e3 dc 17 f9 27 b6 5d 44 |....;+7/....'.]D| -000000c0 d0 30 4b 2e 21 |.0K.!| +000000a0 00 00 00 00 00 34 81 ed 3f e0 b9 5d 01 6e d7 e8 |.....4..?..].n..| +000000b0 45 9f 2c 93 27 28 11 34 b4 a9 32 d5 97 9f ea 05 |E.,.'(.4..2.....| +000000c0 39 90 90 dc e5 |9....| diff --git a/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound b/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound index 0c06ce98d75..975b9fbe599 100644 --- a/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound +++ b/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 81 01 00 00 7d 03 03 77 e7 c3 97 fa |........}..w....| -00000010 59 80 de d1 f5 9f ce e5 a5 38 60 2c 30 b2 64 5b |Y........8`,0.d[| -00000020 6c 0a 56 49 1d 6f 19 57 5a ac 05 00 00 04 00 2f |l.VI.o.WZ....../| +00000000 16 03 01 00 81 01 00 00 7d 03 03 7a 13 72 a9 8d |........}..z.r..| +00000010 6d 7e 8e 9c ba c1 9d 5c 09 87 9e 2f 7b e1 ba 39 |m~.....\.../{..9| +00000020 f8 ee fd 1c a7 08 61 73 b9 d7 be 00 00 04 00 2f |......as......./| 00000030 00 ff 01 00 00 50 00 00 00 10 00 0e 00 00 0b 73 |.....P.........s| 00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 16 00 00 00 17 |nitest.com......| 00000050 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| @@ -9,75 +9,75 @@ 00000070 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 02 |................| 00000080 04 02 05 02 06 02 |......| >>> Flow 2 (server to client) -00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000000 16 03 03 00 39 02 00 00 35 03 03 00 00 00 00 00 |....9...5.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| -00000030 09 ff 01 00 01 00 00 17 00 00 16 03 03 02 59 0b |..............Y.| -00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| -00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| -00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| -00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| -00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| -00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| -000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| -000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| -000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| -000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| -000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| -000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| -00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| -00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| -00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| -00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| -00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| -00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| -00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| -00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| -00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| -00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| -000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| -000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| -000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| -000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| -000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| -000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| -00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| -00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| -00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| -00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| -00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | -00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| -00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| -00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| -00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| -00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........| -000002a0 00 |.| +00000030 0d ff 01 00 01 00 00 17 00 00 00 00 00 00 16 03 |................| +00000040 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000050 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000060 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000070 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +00000080 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +00000090 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000a0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000b0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000c0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000d0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +000000e0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +000000f0 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000100 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000110 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000120 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000130 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000140 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000150 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000160 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000170 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +00000180 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +00000190 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001a0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001b0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001c0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001d0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +000001e0 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +000001f0 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000200 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000210 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000220 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000230 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000240 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000250 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000260 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000270 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +00000280 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +00000290 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002a0 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) -00000000 16 03 03 00 86 10 00 00 82 00 80 67 0c a0 f8 da |...........g....| -00000010 2e d9 9e 9d ef c8 9b 77 f5 fe 25 32 74 49 1d a7 |.......w..%2tI..| -00000020 7d 69 37 2a 94 07 5a 15 e8 f1 1d 36 25 ae 32 e4 |}i7*..Z....6%.2.| -00000030 9c f5 35 fb 54 81 f2 19 4f 8d 6b 64 1a b2 a2 2e |..5.T...O.kd....| -00000040 c4 cb 5b 73 9d 46 97 01 33 d3 b8 a9 18 39 2c ad |..[s.F..3....9,.| -00000050 f2 eb 6b 02 38 44 f8 cf ae ac a6 e6 54 92 29 ae |..k.8D......T.).| -00000060 a6 8a 4e 82 99 f3 77 8c b6 3a a1 5c 4f 25 3b 7f |..N...w..:.\O%;.| -00000070 39 2f cd 51 dc e3 fc 7c 5a 5a 33 e4 af 43 d0 d3 |9/.Q...|ZZ3..C..| -00000080 eb 3b 86 71 af 92 53 6e 02 b9 59 14 03 03 00 01 |.;.q..Sn..Y.....| -00000090 01 16 03 03 00 40 8b e4 6f d3 88 e7 6a e9 aa f2 |.....@..o...j...| -000000a0 4f 67 69 80 bc f1 78 ca a9 f9 29 ce 44 93 81 46 |Ogi...x...).D..F| -000000b0 0e 18 d1 2a 14 8b 3b b5 15 e4 b5 2a bb 88 d4 80 |...*..;....*....| -000000c0 7b 2f 03 c7 83 7c 61 24 29 fe dd bc 49 8a b1 88 |{/...|a$)...I...| -000000d0 41 ac 8a 12 f8 d6 |A.....| +00000000 16 03 03 00 86 10 00 00 82 00 80 6a be 75 35 e3 |...........j.u5.| +00000010 38 f9 8e b5 c3 64 bb 5f 95 95 5e 2c 6a 61 84 8d |8....d._..^,ja..| +00000020 aa 41 88 de 30 55 ba ae 38 48 e5 d9 19 fa ad 09 |.A..0U..8H......| +00000030 94 16 93 df 08 4a a6 0b 0b 53 2a 2a 37 65 cb ed |.....J...S**7e..| +00000040 2c 07 6b 7d 99 6e 14 1d 9b de 60 e8 25 da 0d c5 |,.k}.n....`.%...| +00000050 73 e5 a9 87 25 ce c7 8f 68 88 c5 68 14 ee ac 91 |s...%...h..h....| +00000060 ab 44 fe 31 e0 b5 e1 cd 9b 56 b7 0a 5a d6 b3 54 |.D.1.....V..Z..T| +00000070 9c aa 30 17 ea e2 8c b5 61 89 a7 b1 96 d6 25 0f |..0.....a.....%.| +00000080 30 91 ba 95 2e a8 c0 53 ad 18 e4 14 03 03 00 01 |0......S........| +00000090 01 16 03 03 00 40 b1 5f 16 fb 6e 9d 3b 05 20 be |.....@._..n.;. .| +000000a0 19 0e 6d 74 c1 4a aa 00 db af 58 92 4a 83 f3 23 |..mt.J....X.J..#| +000000b0 e2 6c 0f f2 00 08 0f fd f4 f8 71 b3 c3 8e 8c 57 |.l........q....W| +000000c0 db 98 ff d6 7c f9 26 0b 13 8c 83 36 32 9a 5a 58 |....|.&....62.ZX| +000000d0 0a 41 7d 3f 30 c0 |.A}?0.| >>> Flow 4 (server to client) 00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 e7 d3 34 46 88 |.............4F.| -00000020 0e 7f ae 5b d6 e5 70 d2 7d 99 25 1b 27 89 8a a4 |...[..p.}.%.'...| -00000030 02 03 01 a4 e1 d6 72 af c3 5a 55 f7 56 69 60 91 |......r..ZU.Vi`.| -00000040 49 29 68 36 99 e5 09 ac 7a e3 4f 17 03 03 00 40 |I)h6....z.O....@| +00000010 00 00 00 00 00 00 00 00 00 00 00 88 5b 28 f3 14 |............[(..| +00000020 18 d4 cd f1 1b b8 4b 47 50 0c 76 07 8a f9 ad 9d |......KGP.v.....| +00000030 ba 87 e7 69 cf 47 d7 79 2f 45 55 74 e8 2a 8f d3 |...i.G.y/EUt.*..| +00000040 02 10 ee d8 80 a0 36 9a 5b 70 4d 17 03 03 00 40 |......6.[pM....@| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 71 d0 36 7d 2c 3b 40 e3 a9 3f c1 d0 5e 3a ee d2 |q.6},;@..?..^:..| -00000070 4d 0d b7 f4 83 3e 75 e0 ed 8a fc b2 9b ed 98 a8 |M....>u.........| -00000080 ec 49 65 83 53 e0 79 52 03 2b 78 8a 64 3e 4c 5e |.Ie.S.yR.+x.d>L^| +00000060 43 e0 95 80 4c ce 68 fb 8c ad a8 77 99 d7 53 7f |C...L.h....w..S.| +00000070 b7 bf 03 59 23 f1 b4 3c d8 db 38 f4 b5 9b f5 3f |...Y#..<..8....?| +00000080 12 b6 f3 2a f5 f8 66 57 0c 03 7b 00 16 01 8a 70 |...*..fW..{....p| 00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 76 38 c3 3d 86 d8 58 f2 16 48 94 |.....v8.=..X..H.| -000000b0 46 65 ea 80 46 74 fe 66 7c 72 99 30 b3 05 08 14 |Fe..Ft.f|r.0....| -000000c0 19 e3 ee 6f cf |...o.| +000000a0 00 00 00 00 00 3a fa 64 7c f3 25 08 c6 06 fb 02 |.....:.d|.%.....| +000000b0 ce a0 97 81 c9 ea 53 fc cf 39 b9 8a f7 0c df 2f |......S..9...../| +000000c0 5f 56 62 78 86 |_Vbx.| diff --git a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven index a957c26399e..686011b0fa9 100644 --- a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven +++ b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven @@ -1,180 +1,182 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 ca 01 00 00 c6 03 03 cd 87 c0 5e 7c |..............^|| -00000010 7b d7 c6 77 d9 21 6f 46 00 07 88 61 18 8c b9 d4 |{..w.!oF...a....| -00000020 ad 25 6a 9d 7e 54 cc 70 52 7c 0f 20 67 9b dd 18 |.%j.~T.pR|. g...| -00000030 84 bb 23 7d 53 10 b9 6c 01 ef 30 6f 79 7d 64 5c |..#}S..l..0oy}d\| -00000040 79 3e c1 11 8f 75 cf 83 02 d3 e8 d9 00 04 13 01 |y>...u..........| +00000000 16 03 01 00 ca 01 00 00 c6 03 03 af 29 1d da b2 |............)...| +00000010 1b 14 96 f9 c9 6a 4d 28 cc 1d 9f c4 95 d0 a6 16 |.....jM(........| +00000020 1f 83 3d d6 17 80 5e 4f 9f d9 87 20 cb 34 16 64 |..=...^O... .4.d| +00000030 39 bb 98 16 55 43 38 3a a2 b4 e0 38 02 04 ee 6b |9...UC8:...8...k| +00000040 a6 4e b9 f8 83 09 aa 7b f5 de e0 79 00 04 13 01 |.N.....{...y....| 00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| 00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| -000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 d7 |-.....3.&.$... .| -000000b0 18 8a c1 a5 4d cb 7c f2 7d e4 cf 7a c6 92 28 ee |....M.|.}..z..(.| -000000c0 a6 b4 79 65 bf 2b fb 71 2e a5 2a 58 da 6f 5e |..ye.+.q..*X.o^| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 ee |-.....3.&.$... .| +000000b0 90 71 47 4a 18 b1 78 c4 9a 7d 65 5d 4e b3 88 96 |.qGJ..x..}e]N...| +000000c0 6c b1 bc 2d a3 9d 2d 8e a2 7a 7b eb 94 11 4e |l..-..-..z{...N| >>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 67 9b dd 18 |........... g...| -00000030 84 bb 23 7d 53 10 b9 6c 01 ef 30 6f 79 7d 64 5c |..#}S..l..0oy}d\| -00000040 79 3e c1 11 8f 75 cf 83 02 d3 e8 d9 13 01 00 00 |y>...u..........| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 cb 34 16 64 |........... .4.d| +00000030 39 bb 98 16 55 43 38 3a a2 b4 e0 38 02 04 ee 6b |9...UC8:...8...k| +00000040 a6 4e b9 f8 83 09 aa 7b f5 de e0 79 13 01 00 00 |.N.....{...y....| 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| -00000080 03 03 00 01 01 17 03 03 00 17 4d 4b 33 12 cb ed |..........MK3...| -00000090 f7 a2 55 e7 a6 ab 5b b1 55 16 30 c3 ee e1 5c 14 |..U...[.U.0...\.| -000000a0 b8 17 03 03 00 3e 30 04 2a e5 e8 b8 f3 25 9b a9 |.....>0.*....%..| -000000b0 92 e6 eb d9 fb b6 62 64 e2 de 9d c0 48 68 b3 d7 |......bd....Hh..| -000000c0 0f 8b ad 21 69 c7 f0 d7 96 ff 6a 24 2f 01 c9 e7 |...!i.....j$/...| -000000d0 e9 06 4b 93 94 67 97 44 46 c4 69 2f 0e aa e0 9b |..K..g.DF.i/....| -000000e0 8d 19 f2 2c 17 03 03 02 6d a1 fb 2b 5f 10 e9 62 |...,....m..+_..b| -000000f0 8b ad c1 33 58 f6 a7 89 78 a6 dd 64 ff c2 c7 57 |...3X...x..d...W| -00000100 80 9f 59 be 2d bd f5 b9 8a 6b d9 22 1c fe 10 ea |..Y.-....k."....| -00000110 c4 a5 3e 45 d9 d7 12 cf 48 d5 26 18 49 50 80 69 |..>E....H.&.IP.i| -00000120 44 28 03 3b b6 f8 0a 0e b4 cb 5e 5b 57 0f c0 2f |D(.;......^[W../| -00000130 59 4f 13 e3 9c 02 18 b1 ce 94 78 05 18 64 73 c6 |YO........x..ds.| -00000140 05 89 d1 54 37 18 ea 09 61 08 c5 6a 54 f6 48 44 |...T7...a..jT.HD| -00000150 40 63 6a 53 b9 41 5f 4f 8e 05 e7 31 7b 08 d0 67 |@cjS.A_O...1{..g| -00000160 8e bf 56 c4 56 0a 82 b2 74 6a 89 dd b4 f7 3c 0b |..V.V...tj....<.| -00000170 3c fd 21 1f 00 72 1d 4f be b1 50 44 9a 14 67 7d |<.!..r.O..PD..g}| -00000180 a9 93 30 a2 4e ea 61 c9 fd 44 de 5c 88 36 59 a2 |..0.N.a..D.\.6Y.| -00000190 e3 63 b1 9c ea dd 47 0a ca 63 9e 50 9d ca 57 12 |.c....G..c.P..W.| -000001a0 05 9b fc f1 26 a2 5e 18 9b 32 00 38 1f ce a6 58 |....&.^..2.8...X| -000001b0 58 0f 61 e2 44 c2 89 34 cc f4 fd 9a dc 1a 67 a6 |X.a.D..4......g.| -000001c0 e8 b1 fc 9f dc bd 0b 21 01 49 0d 9b e1 40 00 f6 |.......!.I...@..| -000001d0 33 1a 57 c5 84 c1 98 3d 7f 53 d3 4d 2e 04 5e 40 |3.W....=.S.M..^@| -000001e0 7d 38 80 66 bc c5 40 d9 14 f6 83 26 82 9b c8 14 |}8.f..@....&....| -000001f0 61 aa 6c 1c a1 53 81 f8 b0 7f 06 92 5c af be 57 |a.l..S......\..W| -00000200 1a 54 97 02 27 31 1f 58 52 cf 39 2f 82 26 ae 6c |.T..'1.XR.9/.&.l| -00000210 86 d9 46 cd 38 16 e2 67 62 82 2e 53 7a 86 15 30 |..F.8..gb..Sz..0| -00000220 08 0c a7 e2 85 18 55 79 16 44 4d 50 9e b5 e7 e1 |......Uy.DMP....| -00000230 2c 1e 1d eb e1 83 f3 9e d0 7b 45 b8 1e 51 d9 79 |,........{E..Q.y| -00000240 91 7a b8 90 bc 18 94 69 ad 94 08 e5 23 de 2b fa |.z.....i....#.+.| -00000250 8d ef 23 4c 40 df e1 43 0d 71 51 ef 88 a9 bb 89 |..#L@..C.qQ.....| -00000260 59 87 9c db e1 d4 31 94 a7 f5 af 7d 51 be e9 d0 |Y.....1....}Q...| -00000270 f2 49 12 72 47 65 a0 5b 7d 9f 91 85 f7 e8 d6 90 |.I.rGe.[}.......| -00000280 b3 4d f3 5d 6a 51 96 a9 81 84 72 95 47 e8 0a f5 |.M.]jQ....r.G...| -00000290 8d d6 2a 64 c2 34 1b d8 f0 f9 62 0c be 17 12 9b |..*d.4....b.....| -000002a0 40 a2 c3 8a eb 30 20 04 e4 69 a3 27 90 a6 1a 4f |@....0 ..i.'...O| -000002b0 3f 95 65 e6 9e c7 ad 03 e1 d2 34 d2 84 d5 f6 8c |?.e.......4.....| -000002c0 1e 8a aa e4 75 c0 7f 1d 79 4e 70 10 4e 18 9c eb |....u...yNp.N...| -000002d0 17 76 0c 66 6c 82 72 41 83 98 fc 41 41 4a 07 03 |.v.fl.rA...AAJ..| -000002e0 a6 16 51 0d 60 96 43 0a 97 27 72 42 31 70 6b 02 |..Q.`.C..'rB1pk.| -000002f0 e4 58 b0 15 4f 2e a3 5a ed dc 82 99 82 47 d5 6c |.X..O..Z.....G.l| -00000300 4b b4 68 70 f5 a3 31 36 52 8d af ab d1 ac f6 28 |K.hp..16R......(| -00000310 2e 18 bc 4f 1b 7c a8 ad c3 1f 2f 70 a6 c4 39 c6 |...O.|..../p..9.| -00000320 ae 0f 2e b7 58 c9 c0 2a 4b 34 c2 42 12 e3 5d ed |....X..*K4.B..].| -00000330 d1 ac e1 f1 14 66 d4 09 1c a0 99 82 d3 04 13 2a |.....f.........*| -00000340 a4 20 c4 e7 38 1e 0a 02 4e 96 02 71 9d f6 f7 86 |. ..8...N..q....| -00000350 f7 30 1a 5d 65 4f 17 03 03 00 99 3f 3d 4a 91 ae |.0.]eO.....?=J..| -00000360 0f 80 52 0f 1c d1 a2 75 83 e5 08 d8 1f 9d c8 24 |..R....u.......$| -00000370 fc 85 ba 76 1f 9e 1e 35 a3 dd 45 83 8e b9 55 a6 |...v...5..E...U.| -00000380 3b 26 ae 82 4f 1f 2e 8f e5 25 fb d6 22 0f 55 d6 |;&..O....%..".U.| -00000390 ac fa 93 6d d1 d3 7c 41 af c0 15 5c 8b e1 64 c1 |...m..|A...\..d.| -000003a0 3f a2 c8 9e 48 f5 63 61 3a df 13 6e f4 e3 60 9d |?...H.ca:..n..`.| -000003b0 bc 52 bd b7 94 e9 4b 7a 65 97 28 ac 39 6a 77 a7 |.R....Kze.(.9jw.| -000003c0 86 1d b4 6b e4 15 c4 bd 2b 41 b6 06 ac ff b5 9f |...k....+A......| -000003d0 17 47 b4 a7 1d 69 8b 6e 82 eb f7 39 03 95 10 dd |.G...i.n...9....| -000003e0 18 78 50 58 c8 78 80 ae 45 dc 54 0f 33 cb 4a d2 |.xPX.x..E.T.3.J.| -000003f0 90 00 12 d4 17 03 03 00 35 76 fa bf ab 3f c3 3d |........5v...?.=| -00000400 dd 78 65 cc 35 1e 24 35 4f 7d 3c e4 bb 73 d8 19 |.xe.5.$5O}<..s..| -00000410 56 94 f4 ce ad bc 1d 6a fb 1b 75 01 93 36 2b 44 |V......j..u..6+D| -00000420 3a 3c a3 9b 7c 57 6f 98 24 a3 64 b1 13 47 |:<..|Wo.$.d..G| +00000080 03 03 00 01 01 17 03 03 00 17 c3 9d 29 f6 f8 18 |............)...| +00000090 b9 39 9f 93 b2 f5 ab 30 41 d6 95 40 21 ba f8 8e |.9.....0A..@!...| +000000a0 25 17 03 03 00 52 08 a9 80 f3 24 c6 a6 b6 aa bc |%....R....$.....| +000000b0 30 c2 f7 dd e6 47 10 88 db 0c dd 43 ab 78 bd 16 |0....G.....C.x..| +000000c0 82 7b 4f 26 9c 0e 47 6b 75 79 4e da 8e 43 8b e6 |.{O&..GkuyN..C..| +000000d0 6a 25 0d 47 50 bf 26 c8 16 70 41 1c b2 b5 cd d1 |j%.GP.&..pA.....| +000000e0 34 9b 26 13 92 45 b5 f5 03 04 cf 55 ee ff c8 e6 |4.&..E.....U....| +000000f0 92 9e 04 d9 c5 f5 fd 0f 17 03 03 02 6d f6 33 26 |............m.3&| +00000100 26 da 41 f2 4e 6e ed 41 23 44 29 5f 43 38 7d 24 |&.A.Nn.A#D)_C8}$| +00000110 f7 a1 01 d4 23 a5 bf 85 db 39 86 27 ff 9c e9 ac |....#....9.'....| +00000120 6c 0e 0e 51 c7 95 8d aa f6 59 53 0a 89 d4 e7 2d |l..Q.....YS....-| +00000130 6e f8 66 7d e5 b2 ac e4 7b b2 91 2b 31 c9 2b 4e |n.f}....{..+1.+N| +00000140 92 8f a9 c8 79 21 9a 8f a2 79 29 47 c4 ef ab 80 |....y!...y)G....| +00000150 25 02 d6 8c ae 32 3b 1a 55 0e f9 4a ba 92 b9 61 |%....2;.U..J...a| +00000160 86 39 04 0a a7 d6 eb 95 50 4f 86 1b c9 d1 1d 1e |.9......PO......| +00000170 61 06 43 00 c2 2a a9 e2 06 ff ce 4a fd 6f d0 19 |a.C..*.....J.o..| +00000180 2a 0e ec 14 86 19 9c bc 1d 96 e1 b1 00 b2 19 c4 |*...............| +00000190 15 64 4c 33 54 89 fc 15 01 90 13 3b ff 99 e6 23 |.dL3T......;...#| +000001a0 19 38 4f 67 97 ee ab b3 9f ca 1f 18 7d 45 ef 87 |.8Og........}E..| +000001b0 42 7b 57 51 d0 c3 43 50 35 a3 33 ff 19 df 54 8e |B{WQ..CP5.3...T.| +000001c0 e9 98 2f 46 93 87 b4 b1 c2 73 04 4f 06 5b 3c 0a |../F.....s.O.[<.| +000001d0 c3 87 6c 68 68 b4 61 a2 33 bd 11 06 93 19 fb 05 |..lhh.a.3.......| +000001e0 c3 e6 3f 14 e5 a6 6d ec 48 56 a6 37 60 81 a4 cd |..?...m.HV.7`...| +000001f0 89 b5 4e c8 dc 99 79 66 5e 40 44 de 4a 22 9a ce |..N...yf^@D.J"..| +00000200 3d c4 a0 17 03 45 e6 28 70 27 f5 24 e1 81 7a 5f |=....E.(p'.$..z_| +00000210 5d 6e 6c bc 28 c3 fb b1 8b 18 fa 3d 9d f3 c3 a5 |]nl.(......=....| +00000220 f0 41 7a 0d 87 c1 70 77 d3 3a fa ef 2b 11 9b 61 |.Az...pw.:..+..a| +00000230 12 f8 d1 25 73 bc 79 bf ee 9a 5e e0 3b fb 06 da |...%s.y...^.;...| +00000240 7e d6 08 aa 13 73 8a 8c 97 d7 5a e4 dc 88 51 60 |~....s....Z...Q`| +00000250 8c 61 51 65 f6 d0 4e 7d b0 b1 23 2c 69 77 20 fe |.aQe..N}..#,iw .| +00000260 d1 ff 13 57 d8 c5 58 1f 3c e9 86 f4 3a 45 1a 9c |...W..X.<...:E..| +00000270 c2 e0 4d da 67 1b 81 62 bf 07 de a6 ea 74 81 e3 |..M.g..b.....t..| +00000280 ba 1b 1f bf b0 d3 d3 08 c0 23 5f 05 d5 1f 41 51 |.........#_...AQ| +00000290 f2 11 2e 36 ed 00 f8 b5 ea f1 4c 0b b8 d0 a3 cc |...6......L.....| +000002a0 c6 a7 2a ee 1f 6c 6b 33 0d 38 5b 5c 6e f4 53 d2 |..*..lk3.8[\n.S.| +000002b0 6e 90 5b ce 44 e7 f1 50 1e 12 21 76 35 d1 2f 49 |n.[.D..P..!v5./I| +000002c0 a1 27 66 00 93 27 27 34 5d e5 ed 4b 6f 7e 3d e3 |.'f..''4]..Ko~=.| +000002d0 78 de 2f 48 9f 4c 36 a7 5d 62 98 1e 2c ee 82 3c |x./H.L6.]b..,..<| +000002e0 18 17 2d 80 f4 a2 ac e9 a6 c8 2c b9 92 d1 9e 2b |..-.......,....+| +000002f0 5f 3e 33 56 03 b5 76 51 ea c7 af 1c 42 8e 0e 65 |_>3V..vQ....B..e| +00000300 f7 0f ad 36 9f fe b5 a0 06 31 f0 89 02 b4 bf c3 |...6.....1......| +00000310 8e 2f 52 4d 97 99 dd 95 0f c4 32 9e 81 55 d1 2a |./RM......2..U.*| +00000320 05 ff b5 7a 02 0f 6f 1b ef f1 de 48 dc a8 f8 44 |...z..o....H...D| +00000330 35 8c eb df 6b 78 cd 89 75 ca ef 31 ba 8f b8 ff |5...kx..u..1....| +00000340 a3 74 39 ce 42 a0 01 8b db 68 34 21 0a bf 84 fd |.t9.B....h4!....| +00000350 5f 28 87 d4 09 b2 91 c2 f3 1f b8 39 da 2b 55 3c |_(.........9.+U<| +00000360 46 a2 fa 3d 65 eb 41 0c 37 c8 17 03 03 00 99 e8 |F..=e.A.7.......| +00000370 25 eb 99 2f 80 e2 09 ed 2f b9 78 90 7c dc e2 4a |%../..../.x.|..J| +00000380 78 19 49 46 a8 e7 82 a0 85 84 71 da 80 fb d2 5d |x.IF......q....]| +00000390 28 c4 69 cf ac 1c bc 1e ba 90 5c 0a ec dd 31 5c |(.i.......\...1\| +000003a0 87 d0 4f 31 3f 62 cd 91 1e 99 a5 08 c6 de 6c 75 |..O1?b........lu| +000003b0 91 be 31 83 12 5b fd 5a eb 96 ae 70 9c 06 c9 ee |..1..[.Z...p....| +000003c0 63 e9 3c a0 5b 9c 55 cb cd 9d a2 31 33 17 92 fa |c.<.[.U....13...| +000003d0 dc 34 20 43 71 92 8b 16 dd 1c 29 f5 ec a2 e4 ad |.4 Cq.....).....| +000003e0 d6 21 27 37 32 0c 7b f1 60 7f 58 aa fc d6 ae f3 |.!'72.{.`.X.....| +000003f0 c9 7b 5f 59 39 cf 79 ab 5b a3 7e ea 13 72 51 9f |.{_Y9.y.[.~..rQ.| +00000400 a9 c5 fc fb c0 da 39 2a 17 03 03 00 35 b7 6d ed |......9*....5.m.| +00000410 8d d3 c6 09 fd 9b 6b be 6e bc 01 64 3b a1 4e 2d |......k.n..d;.N-| +00000420 3d 85 e3 5b 4b 7b 44 49 81 fd c8 d9 07 fe e5 53 |=..[K{DI.......S| +00000430 ab 5f a3 64 f6 be 22 79 80 52 f0 ee 3c 1e 4e 65 |._.d.."y.R..<.Ne| +00000440 0e e3 |..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 1e e0 29 6d d1 38 |............)m.8| -00000010 a6 03 d7 fc 2b df a4 a4 d0 ae 87 01 b8 82 5d eb |....+.........].| -00000020 3c 25 3e a1 33 89 b5 05 eb bc 02 0f ad 84 f0 2b |<%>.3..........+| -00000030 5f 14 af 0d f8 f1 08 e3 ca c1 8e ad 4b a5 a0 09 |_...........K...| -00000040 b8 a0 4f bf e4 0f 93 a9 4a 35 35 26 22 d7 04 03 |..O.....J55&"...| -00000050 70 95 4f 80 df d4 47 5b 21 14 27 d6 17 ea 32 6e |p.O...G[!.'...2n| -00000060 ea 3a ca 31 7c f2 d1 46 a2 ef 47 b9 16 d6 18 d5 |.:.1|..F..G.....| -00000070 17 35 71 9d 14 37 63 cd e1 c6 ff 3d ec a5 d8 53 |.5q..7c....=...S| -00000080 48 d5 d8 0b 75 39 c1 d2 66 ad 97 4e 5f eb c3 c7 |H...u9..f..N_...| -00000090 e0 77 95 fd 16 84 e2 a3 6a f2 a8 88 5e 4c 86 be |.w......j...^L..| -000000a0 81 a5 f2 6b 12 86 63 f1 4f a6 8d 63 7c 07 0f 8d |...k..c.O..c|...| -000000b0 53 d5 d4 00 c7 b7 2a ef b2 1d 07 4e 43 d6 25 35 |S.....*....NC.%5| -000000c0 c9 b1 fa 91 d1 f7 87 c6 98 c7 e7 c2 c3 7d 42 09 |.............}B.| -000000d0 e5 3c 50 83 1b 20 ef ec e4 ac 2e f2 3e 03 73 52 |..sR| -000000e0 2e 1d 20 cf e2 8d 15 c3 c7 a6 2f 68 b5 8e 5f bc |.. ......./h.._.| -000000f0 c5 73 61 ff 52 3c b0 7b 47 82 47 a0 73 f8 1c ab |.sa.R<.{G.G.s...| -00000100 4d ea 15 fa 94 e0 7f 70 c1 c8 9c 55 f0 96 38 42 |M......p...U..8B| -00000110 76 d4 26 6d a7 73 11 59 43 19 2f 49 70 a9 18 1c |v.&m.s.YC./Ip...| -00000120 12 9e ee d3 eb ca 1c c0 3b e1 99 e3 c2 25 de 39 |........;....%.9| -00000130 1a 15 e0 d7 20 9d 1b 95 74 8c ee 96 7b 5e de 13 |.... ...t...{^..| -00000140 99 56 54 a2 31 7b e9 96 02 9e 86 7b 15 9d c6 3e |.VT.1{.....{...>| -00000150 24 a5 19 e5 8e de 85 97 05 68 4f 39 d1 49 05 c9 |$........hO9.I..| -00000160 7a 54 90 29 e7 93 ec 8e 6f cc 73 73 82 7d 72 8d |zT.)....o.ss.}r.| -00000170 4a 85 29 7f a5 53 13 26 16 b2 fa c3 ce 1f 8b ae |J.)..S.&........| -00000180 e6 60 8c 2d b0 64 66 d4 29 7c b5 2d 1d 11 c5 09 |.`.-.df.)|.-....| -00000190 bb a5 44 c6 c8 af e6 f1 d5 f8 d9 45 97 64 7f 03 |..D........E.d..| -000001a0 02 f7 f5 9f cb 31 1e 89 e4 5d a0 e9 34 db be 28 |.....1...]..4..(| -000001b0 51 15 68 54 01 7c e5 1d b4 05 d2 d6 24 ca 10 69 |Q.hT.|......$..i| -000001c0 31 bf 8b 7a ee d9 bf e1 2a d4 7c c8 e8 79 ca dd |1..z....*.|..y..| -000001d0 0f 73 09 c8 cf 97 28 78 04 5b 04 51 44 c4 5f d1 |.s....(x.[.QD._.| -000001e0 dc da 4f f5 d9 5c 9c b1 ea f8 1b f7 43 90 c0 c0 |..O..\......C...| -000001f0 fd 82 56 e3 71 15 18 5e 7e 5c 61 5e b3 80 c1 1c |..V.q..^~\a^....| -00000200 22 92 32 67 23 f6 3b 74 e4 20 4e 1f fb f8 89 55 |".2g#.;t. N....U| -00000210 e7 3c 18 30 24 77 7c 33 5c 89 91 60 65 14 06 9e |.<.0$w|3\..`e...| -00000220 e2 6d f0 07 84 4b b4 14 e8 17 03 03 00 a3 a7 e1 |.m...K..........| -00000230 f7 26 48 56 da 6d ef a5 f4 5f 19 52 37 9e e7 6d |.&HV.m..._.R7..m| -00000240 28 07 70 ee 1e de 85 2b 7a 2d bf eb 48 06 f5 d4 |(.p....+z-..H...| -00000250 ea 4d 83 86 59 d4 14 4f 46 bc 17 89 f1 f5 37 0e |.M..Y..OF.....7.| -00000260 84 60 6e ba 73 d7 c1 bc 6f d7 aa cf f0 36 96 a2 |.`n.s...o....6..| -00000270 83 60 81 6f 48 6c 9d 87 e5 b6 5e 77 ab c5 e3 cb |.`.oHl....^w....| -00000280 8e 55 94 dc 94 f3 8a ce cb f7 b4 d5 33 55 df 88 |.U..........3U..| -00000290 22 44 04 ee 4e f5 30 e7 30 94 dc 95 2d 97 2c e4 |"D..N.0.0...-.,.| -000002a0 34 58 4d 38 9e 25 61 96 c1 37 66 34 2b be ee e6 |4XM8.%a..7f4+...| -000002b0 ee 39 73 89 a3 aa 1b 0a 5a bf 44 23 4e 19 5c c4 |.9s.....Z.D#N.\.| -000002c0 3f 27 47 5c 40 67 6c 50 b8 3f 7c c9 97 f0 55 02 |?'G\@glP.?|...U.| -000002d0 16 17 03 03 00 35 82 8b 0d 4e 87 3c c6 bc 41 8b |.....5...N.<..A.| -000002e0 ec ab 71 9d 57 7b e6 22 e4 87 82 61 5d f8 69 31 |..q.W{."...a].i1| -000002f0 8a 2c be 2c d8 4d 2f dc 9a 91 31 7a ab d8 a4 0e |.,.,.M/...1z....| -00000300 ba cb fc ef 17 a4 7c 87 ca 13 bb 17 03 03 00 13 |......|.........| -00000310 3b d0 da 9f d4 be fa 59 7a 30 8b 7e 8e a0 99 c0 |;......Yz0.~....| -00000320 c2 36 f3 |.6.| +00000000 14 03 03 00 01 01 17 03 03 02 1e a8 48 8d 47 f6 |............H.G.| +00000010 3d d8 59 5b 26 9e bd fc d1 15 7c e1 37 1b db 3c |=.Y[&.....|.7..<| +00000020 e4 02 98 fd aa cc a6 45 97 6e c5 18 4e 45 8e d6 |.......E.n..NE..| +00000030 84 7a b5 e4 da 8b 17 34 e5 fb 21 3c f6 02 c2 5c |.z.....4..!<...\| +00000040 ea 57 ea 16 67 4a 6d b2 0e 5a 39 f8 6b 11 84 bd |.W..gJm..Z9.k...| +00000050 43 80 03 40 5e d2 d2 54 2e d1 38 bc 9a 16 4f 21 |C..@^..T..8...O!| +00000060 0e 07 38 b5 80 21 16 c6 a1 bb 23 79 a6 df ef 27 |..8..!....#y...'| +00000070 dc 30 3c 4a 53 b1 5c 54 a7 fb ff 73 e2 12 ab 90 |.0..*..`.d~q| +000001b0 45 26 b8 91 26 cc d6 bf d5 4d 26 3f 4f c8 73 99 |E&..&....M&?O.s.| +000001c0 a7 50 9d 14 09 b6 07 1a af aa 9b 02 31 b2 c6 22 |.P..........1.."| +000001d0 ca 3e e0 2f 27 87 27 2e 96 f4 b4 ba c6 01 77 d3 |.>./'.'.......w.| +000001e0 52 09 ea 79 9b ee b4 6a 41 29 b1 de de 74 6b b2 |R..y...jA)...tk.| +000001f0 11 b1 58 90 5c 6a 0d b5 51 4b 2e 1b 3e e6 f4 17 |..X.\j..QK..>...| +00000200 8e 8a 1d 1e c8 bd 55 3a fc f4 90 73 14 5f 63 1b |......U:...s._c.| +00000210 22 f0 81 fd 70 05 ca b2 fd 90 3c 9d 2e 73 d3 8c |"...p.....<..s..| +00000220 f0 0a 59 9e 46 fe 8c e2 22 17 03 03 00 a4 78 2b |..Y.F...".....x+| +00000230 ec c5 5e 71 85 c6 e5 5d 75 f3 b5 3d 55 de 1c f9 |..^q...]u..=U...| +00000240 06 92 be df ef 77 31 4b f3 13 b8 c7 7a 68 ec 1b |.....w1K....zh..| +00000250 e2 7c c0 ff b5 6f c2 62 bd 34 23 fd 6a 39 c7 ef |.|...o.b.4#.j9..| +00000260 91 47 77 7e 32 2e a9 b2 85 ae 01 3e 61 43 8a 93 |.Gw~2......>aC..| +00000270 72 14 e1 b7 a5 14 4b ca 6e cb 4d e7 a3 cd 74 98 |r.....K.n.M...t.| +00000280 4e 08 a4 d4 34 ea 73 17 4b 20 8b 40 03 10 a0 33 |N...4.s.K .@...3| +00000290 c9 2f c0 4c 3b a2 2c 61 3c ab ec e3 c0 e8 e2 d6 |./.L;.,a<.......| +000002a0 a0 85 fa 26 26 a9 65 dc 70 5b 8f b7 3f 9e b3 fb |...&&.e.p[..?...| +000002b0 44 36 62 79 75 af ef 94 05 6b d2 44 07 51 ae 91 |D6byu....k.D.Q..| +000002c0 ea e3 e7 d2 f4 2f 19 17 38 aa 1c ae cb 88 db 0b |...../..8.......| +000002d0 66 5a 17 03 03 00 35 6d d9 23 d1 3c c3 25 7b 5d |fZ....5m.#.<.%{]| +000002e0 8a 1a 41 00 00 f8 0c a7 3e 53 4e e5 f6 cb 11 3f |..A.....>SN....?| +000002f0 9c 66 62 80 98 6c 55 19 b1 6f 00 5d 46 93 d2 0b |.fb..lU..o.]F...| +00000300 79 58 1c d6 d7 f9 fc fb 38 c5 32 63 17 03 03 00 |yX......8.2c....| +00000310 13 72 a9 fd 60 5c cf 68 b3 32 15 04 33 1c e1 5f |.r..`\.h.2..3.._| +00000320 11 11 9e 8c |....| >>> Flow 4 (server to client) -00000000 17 03 03 02 90 a2 a0 e4 83 63 ad 8d d5 45 25 dc |.........c...E%.| -00000010 41 02 31 28 8d b0 87 85 66 b8 9c 36 f3 1f 97 87 |A.1(....f..6....| -00000020 8c c9 e6 b4 67 1e 42 ab 84 c4 eb 0a 41 b1 0f 50 |....g.B.....A..P| -00000030 25 c3 7e 69 20 cf 8a d0 56 79 61 e3 e1 5b cc a4 |%.~i ...Vya..[..| -00000040 24 5a c7 2d 3b 17 33 92 59 6c 7e 29 a9 a2 2c 73 |$Z.-;.3.Yl~)..,s| -00000050 3e b1 65 32 3d 6a 2b 61 5d 76 c4 66 0e 4f f1 da |>.e2=j+a]v.f.O..| -00000060 dd d3 7e 29 3d f5 42 99 9e 04 60 a4 9a a1 c0 f7 |..~)=.B...`.....| -00000070 54 4e d5 58 73 85 02 83 38 ba 4e 93 9a 69 68 07 |TN.Xs...8.N..ih.| -00000080 71 c9 a7 e4 83 51 4c 11 21 26 b2 dd ad 4b 2a ef |q....QL.!&...K*.| -00000090 23 9b b0 f6 d6 96 9f 99 1f 69 fe 35 28 86 49 bc |#........i.5(.I.| -000000a0 ec 97 11 4d 4e b7 c1 c2 da 6c ae c7 40 b9 2a 1f |...MN....l..@.*.| -000000b0 ff 9d 9d ea 90 b9 61 6f 76 ae fe 55 70 f6 ee 54 |......aov..Up..T| -000000c0 54 62 6d 19 9a fc 40 16 e5 c2 e2 3e d1 68 c6 09 |Tbm...@....>.h..| -000000d0 be 54 64 25 8a a0 2b e6 b3 14 7e 74 17 91 f0 de |.Td%..+...~t....| -000000e0 87 e8 3c 3e 58 8d 1b b2 4e 2d 7d c1 f8 aa 16 ca |..<>X...N-}.....| -000000f0 2a 3e 8f aa 52 14 e4 f2 2a b9 6e 62 46 ab ed 3a |*>..R...*.nbF..:| -00000100 ff a1 51 53 92 7a 78 c4 ed 9d fd 1f b4 62 2e e7 |..QS.zx......b..| -00000110 cc 9d 09 fa 06 2e 9e 55 e5 98 9e b8 be e9 12 94 |.......U........| -00000120 33 58 6b be 71 a1 4f f8 a0 83 85 f8 7e b4 28 a7 |3Xk.q.O.....~.(.| -00000130 ee 1b ac 3c 46 b6 ac 60 af 5d cc b0 a8 2c 3f 95 |.....Z.| -00000210 6b 5c d2 4d b2 20 35 63 9e 83 c0 7e 83 60 46 57 |k\.M. 5c...~.`FW| -00000220 c0 80 0d d7 b9 9f 14 c0 58 2d 48 2a cc 8c 1d 32 |........X-H*...2| -00000230 2c 34 ec 10 f2 34 b4 28 e1 0e 83 38 c4 2e 5a 09 |,4...4.(...8..Z.| -00000240 ff e6 3f d3 9a 32 8e 33 9e 31 18 e5 1d 6b 97 12 |..?..2.3.1...k..| -00000250 9b 93 84 86 62 8a 0a 8a ab 8d 37 68 af a1 ec 8e |....b.....7h....| -00000260 38 c8 47 ef 10 f8 64 7c e1 13 0a 33 eb c2 4b bf |8.G...d|...3..K.| -00000270 47 49 6d 93 3c c9 44 aa 74 67 a9 93 dd de 66 47 |GIm.<.D.tg....fG| -00000280 1e b3 55 47 b1 16 88 68 82 24 d6 b8 81 b0 5a b6 |..UG...h.$....Z.| -00000290 27 7a f8 0b 5c 17 03 03 00 1e a5 9b 8c d2 3e 96 |'z..\.........>.| -000002a0 f3 49 7a ed d9 fc 33 62 15 12 43 76 11 f9 dc fc |.Iz...3b..Cv....| -000002b0 ea d2 d7 87 22 6f 9e 3d 17 03 03 00 13 e1 30 4e |...."o.=......0N| -000002c0 4c 1d 02 78 57 a5 ee 8f 1c 5f 19 f0 57 3a 8d 7e |L..xW...._..W:.~| +00000000 17 03 03 02 90 2e 71 49 81 51 71 9c 2f da 1e dc |......qI.Qq./...| +00000010 22 c0 a2 59 13 ad 41 ae 7b 18 56 d0 00 7b b5 cf |"..Y..A.{.V..{..| +00000020 47 e7 bc 8e 92 9e dc 88 78 3e 40 8e 8b 01 b0 30 |G.......x>@....0| +00000030 8f 7e 88 95 77 ed de 31 bf c5 78 ba a1 44 55 ec |.~..w..1..x..DU.| +00000040 b6 df 49 a9 df a0 92 b2 be b7 2c 1c 39 1b a0 63 |..I.......,.9..c| +00000050 18 e5 12 b7 5a a5 85 14 97 7d 9e e1 80 b7 15 c5 |....Z....}......| +00000060 2f ca e3 3b 48 91 42 07 f4 49 25 99 2c ee b8 b5 |/..;H.B..I%.,...| +00000070 05 a2 34 7d bb c0 87 4c f3 a8 07 89 fe b7 08 2c |..4}...L.......,| +00000080 e2 0b 27 6f 49 88 80 2f 3b 9c ae a6 3e 38 74 23 |..'oI../;...>8t#| +00000090 53 70 f5 84 0f 77 d4 94 68 f9 86 18 2f dc e1 94 |Sp...w..h.../...| +000000a0 3c e1 2c f2 84 07 f5 3c 88 99 63 ef a1 96 73 f9 |<.,....<..c...s.| +000000b0 46 43 c2 92 be 04 b8 6b 9e db e1 7f 63 b1 d4 15 |FC.....k....c...| +000000c0 36 2c 37 e3 c2 24 b2 4c c5 60 96 15 3b 20 01 67 |6,7..$.L.`..; .g| +000000d0 e5 52 9a 4f 17 6c 0a f1 a0 a3 31 48 e5 31 8e d3 |.R.O.l....1H.1..| +000000e0 b9 49 38 d2 55 4d 40 8e a2 bf dd 0f 19 25 42 55 |.I8.UM@......%BU| +000000f0 06 57 22 c5 06 c9 59 13 f7 c7 56 b1 68 20 f4 62 |.W"...Y...V.h .b| +00000100 19 0a 5d ab 5f 81 c6 50 b7 a2 f8 ce 55 f2 b6 6c |..]._..P....U..l| +00000110 67 39 75 82 1b a1 6b 85 58 37 c0 a5 12 64 a6 ee |g9u...k.X7...d..| +00000120 2e f8 f0 dc d2 50 08 47 0f 15 c8 37 2d ba 69 64 |.....P.G...7-.id| +00000130 e9 ea 7b fa 16 91 ed b6 24 0d fb e8 aa 74 6b 74 |..{.....$....tkt| +00000140 2d 78 2d 1c 2b 98 8e ab 74 6d 06 a3 00 8a e5 be |-x-.+...tm......| +00000150 c0 68 09 05 e0 95 0d c1 27 8a cf 05 09 0a 7c b9 |.h......'.....|.| +00000160 a1 3a 9b 45 3d d4 5d 16 64 5b d5 a3 6c d2 12 78 |.:.E=.].d[..l..x| +00000170 4f 6b ba 3a fe ad 35 9e 5e 0c 5f d4 f3 32 a2 0b |Ok.:..5.^._..2..| +00000180 f1 af d4 e5 f1 91 c6 6c 47 6b 30 a7 2f bf 60 05 |.......lGk0./.`.| +00000190 e3 c0 2d 9c 34 f2 f0 6b f2 ce 7f 19 d0 86 26 b0 |..-.4..k......&.| +000001a0 e1 7e 7b e0 0e 3d e7 f6 3c 7f 42 bc 9f a6 0a 25 |.~{..=..<.B....%| +000001b0 eb cf 1b 4b 44 10 df 7d f1 1f e3 a9 ea 4f 6d 52 |...KD..}.....OmR| +000001c0 70 b2 f0 0b a9 c5 bc 66 46 21 4d 92 c4 c3 f6 71 |p......fF!M....q| +000001d0 eb 46 c0 f3 e7 6f 4a ee 37 ad 8a ea 3b aa 51 79 |.F...oJ.7...;.Qy| +000001e0 d5 d5 18 7e e8 ae 31 1a db 16 04 d8 3c 94 17 f6 |...~..1.....<...| +000001f0 ad 8f 8b 5d 7d 14 fb b4 e9 b4 7e bb 75 f1 df de |...]}.....~.u...| +00000200 6f 0a 0d a8 f9 b5 d8 53 73 36 88 77 db e6 0e 84 |o......Ss6.w....| +00000210 fc 94 6b c9 cc 74 0f 01 40 39 c4 d0 66 2d 23 76 |..k..t..@9..f-#v| +00000220 9f 0d a1 53 94 a2 dd 56 83 9e 62 39 10 13 39 40 |...S...V..b9..9@| +00000230 55 09 b6 77 d2 22 9c 49 ef f9 af 93 ee d1 cf 3d |U..w.".I.......=| +00000240 1f 29 ef 27 94 3c 6d 23 d6 7c 33 e1 f7 cd 70 05 |.).'.Z..~..i7.| +000002b0 b0 90 43 11 e6 76 5e 2d 17 03 03 00 13 4b 69 75 |..C..v^-.....Kiu| +000002c0 3d 46 35 f6 85 4b 0b 6e f4 6b 30 2a 28 37 3c f1 |=F5..K.n.k0*(7<.| diff --git a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given index 6943bf65690..016b7da4dfe 100644 --- a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given +++ b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given @@ -1,149 +1,151 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 ca 01 00 00 c6 03 03 e4 83 a9 75 06 |..............u.| -00000010 0f 8b c9 35 1e 62 89 7f a8 df 7c 93 b6 f0 8f 94 |...5.b....|.....| -00000020 ea 31 dc 66 11 66 bd 77 33 54 bf 20 38 77 15 8d |.1.f.f.w3T. 8w..| -00000030 b4 21 50 72 6f 95 61 6c 15 b8 35 c9 92 10 72 99 |.!Pro.al..5...r.| -00000040 bc 41 03 53 7c 5e 7b b3 a4 2e b4 19 00 04 13 01 |.A.S|^{.........| +00000000 16 03 01 00 ca 01 00 00 c6 03 03 c3 82 3b bf 9c |.............;..| +00000010 31 25 31 c7 8d 18 7f c1 28 22 0f 23 0c 13 b8 81 |1%1.....(".#....| +00000020 a8 e8 35 00 92 0a 13 21 8d 76 43 20 9e 3a 45 91 |..5....!.vC .:E.| +00000030 73 a0 99 70 ab 96 99 2b ae 4a b1 2a 89 3c 74 94 |s..p...+.J.*.>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 38 77 15 8d |........... 8w..| -00000030 b4 21 50 72 6f 95 61 6c 15 b8 35 c9 92 10 72 99 |.!Pro.al..5...r.| -00000040 bc 41 03 53 7c 5e 7b b3 a4 2e b4 19 13 01 00 00 |.A.S|^{.........| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 9e 3a 45 91 |........... .:E.| +00000030 73 a0 99 70 ab 96 99 2b ae 4a b1 2a 89 3c 74 94 |s..p...+.J.*.8..`...1&.| -000000b0 db ef e2 b1 99 55 c8 f9 f3 a0 81 19 12 a7 63 85 |.....U........c.| -000000c0 5a 26 2d d1 1c ad 5d ae d6 4b 66 93 62 d7 fe 08 |Z&-...]..Kf.b...| -000000d0 40 e9 fa 16 8b 89 f8 04 e8 33 67 20 2b 21 91 a0 |@........3g +!..| -000000e0 c6 0a 87 ff 17 03 03 02 6d 79 97 6c 2f f6 01 7b |........my.l/..{| -000000f0 3a 49 0e 1a 00 96 10 fd 7f 77 db 76 b2 d4 e4 68 |:I.......w.v...h| -00000100 46 4e 4f 3c 64 54 ca 27 9a 5c 78 98 f4 96 a4 fe |FNO.....u.(..| -00000120 ff d8 ec 27 2c f2 4c e5 a0 6e 88 ce 67 6e 35 f4 |...',.L..n..gn5.| -00000130 e5 d5 96 2d 40 af fa 88 12 8a 48 24 2c f9 82 f5 |...-@.....H$,...| -00000140 cb a4 6e 95 a6 53 bc 79 f7 6a ef 66 77 bc 46 f0 |..n..S.y.j.fw.F.| -00000150 1b 0d 6b 5c 76 82 15 c4 d0 1c dd ec cc ce 09 93 |..k\v...........| -00000160 ce 21 55 9b d8 8a 11 1b 0c 24 fa 9e 5f 29 4a f1 |.!U......$.._)J.| -00000170 2a 2e ad c0 6d 6d 46 06 5b c9 75 b3 3e 32 45 67 |*...mmF.[.u.>2Eg| -00000180 05 26 cc d8 a8 4a a9 b1 67 71 a6 82 1c dc f0 15 |.&...J..gq......| -00000190 6d 25 f5 6e be a2 5f 45 39 dc d1 2e df fa e1 e9 |m%.n.._E9.......| -000001a0 48 ca 7a 78 fa 0e 53 d1 5c 8f c2 40 91 d5 fa 40 |H.zx..S.\..@...@| -000001b0 7e a1 52 23 c8 56 1f 31 17 91 5c 38 bb 54 56 f3 |~.R#.V.1..\8.TV.| -000001c0 1e 14 90 43 b7 ef fd 56 b5 ae 13 90 97 dc 60 15 |...C...V......`.| -000001d0 67 72 fc c2 0a 32 90 be ec de 69 16 d3 1b 22 2c |gr...2....i...",| -000001e0 25 9f 91 27 a7 6d 8c a4 de 02 fd 0e da bf ca 71 |%..'.m.........q| -000001f0 77 9b 56 b8 07 e8 80 00 9b d9 36 1c 09 4f 9f 54 |w.V.......6..O.T| -00000200 76 d5 76 f4 9a 03 94 bb 9e 93 f0 b5 3c a1 71 ec |v.v.........<.q.| -00000210 b3 83 3a 06 b4 46 97 bf ef bb f0 26 94 4e b0 08 |..:..F.....&.N..| -00000220 3b ec 81 20 66 92 11 85 a0 c2 90 fd c5 bc ae 39 |;.. f..........9| -00000230 2c 87 ec e4 5d 59 ee b4 e9 0d f7 2a e0 3b 2a 94 |,...]Y.....*.;*.| -00000240 1a 79 2f e8 5c 88 d3 61 2e 47 c0 f3 c4 01 84 a9 |.y/.\..a.G......| -00000250 cf f6 36 13 cb 4b 0b f7 9a 14 f1 d5 0e 10 80 fd |..6..K..........| -00000260 11 79 20 20 ae 56 5e de 58 53 19 38 26 e2 ac bc |.y .V^.XS.8&...| -00000270 0c 40 38 8b f9 67 62 4c 42 7d 18 4f 27 e9 53 96 |.@8..gbLB}.O'.S.| -00000280 78 4b fa 44 fe c2 c3 d9 99 f2 2c 59 2b 2b 2c 88 |xK.D......,Y++,.| -00000290 5b dc a8 98 3d 17 14 09 70 ce e4 02 8b 3c 5d 94 |[...=...p....<].| -000002a0 44 ac ba 57 2d a9 bf b8 70 e9 b8 a8 c3 b8 90 da |D..W-...p.......| -000002b0 ec b1 b4 57 d6 e3 0f 41 82 bb 21 4a 57 dc ac 4b |...W...A..!JW..K| -000002c0 89 34 75 fc c4 56 6b 70 3d 83 2b fa be c8 2b cd |.4u..Vkp=.+...+.| -000002d0 f8 4f 9f 9e 9a 0e d2 d0 46 cd 21 a5 f7 07 a6 2a |.O......F.!....*| -000002e0 85 7b 30 92 78 a2 da a5 1d 1c 1c 54 63 4b 66 b2 |.{0.x......TcKf.| -000002f0 f1 a7 c4 43 57 97 7f 28 37 e7 15 62 9b 1c f5 90 |...CW..(7..b....| -00000300 0c 19 36 1a c1 48 48 e5 7d 56 93 3c 13 e3 cd 6a |..6..HH.}V.<...j| -00000310 aa aa ba d5 24 95 c7 df 9c a9 76 6c 07 bf 09 2d |....$.....vl...-| -00000320 4b 7b 55 94 37 ec d4 69 ce ab 0f 48 37 74 37 99 |K{U.7..i...H7t7.| -00000330 83 0d 60 8a 73 56 fb e2 9e 0c 39 0e 23 bf 68 b2 |..`.sV....9.#.h.| -00000340 92 51 12 bc cf 1b af 9d 7c fe 77 14 c8 66 4a 6f |.Q......|.w..fJo| -00000350 91 06 55 6a 11 61 17 03 03 00 99 c2 bf 26 a6 fa |..Uj.a.......&..| -00000360 67 16 a3 b9 1f 36 f8 4f 5d 59 b1 be 43 3a 70 01 |g....6.O]Y..C:p.| -00000370 c0 3a 4b c5 20 b1 22 49 04 22 bb 7f 5f f4 bb f8 |.:K. ."I.".._...| -00000380 35 03 0e dc ba ce de 2a 25 ea 96 dd 3d 64 34 90 |5......*%...=d4.| -00000390 30 f8 34 22 bb e4 94 00 bb b3 ea 3c d2 87 90 9a |0.4".......<....| -000003a0 86 76 6b b7 e3 78 fc 35 10 50 ce b6 c0 71 52 ae |.vk..x.5.P...qR.| -000003b0 a5 f7 bf 8c 5e 5d c1 96 c7 92 6f f0 04 87 d9 a8 |....^]....o.....| -000003c0 72 f4 9e ed 6d ab 28 42 7c c8 60 39 81 66 74 a1 |r...m.(B|.`9.ft.| -000003d0 79 79 6a 59 02 29 b8 14 12 34 a7 96 8f e0 c1 d6 |yyjY.)...4......| -000003e0 4e da e2 63 22 c1 60 b1 87 64 d3 80 b9 c4 df 9a |N..c".`..d......| -000003f0 5f 2c 22 91 17 03 03 00 35 9a 62 4d a2 ba 27 31 |_,".....5.bM..'1| -00000400 fc 8e 23 cc 5f f0 5c 8c 9b c1 b0 ae 7b b8 fa e2 |..#._.\.....{...| -00000410 f3 af 6c 6c ac 86 1e e1 2b 9f 14 a1 f3 5f b5 f9 |..ll....+...._..| -00000420 76 b6 dd 73 f5 6a 08 29 f1 29 9e 79 87 aa |v..s.j.).).y..| +00000080 03 03 00 01 01 17 03 03 00 17 84 17 5a 31 cf 40 |............Z1.@| +00000090 61 37 2b 5a 28 91 d9 e1 7b f2 50 14 8e 7b 40 30 |a7+Z(...{.P..{@0| +000000a0 4b 17 03 03 00 52 ad d1 15 51 c8 89 48 44 23 64 |K....R...Q..HD#d| +000000b0 8a b6 8d ac 08 47 ed 65 1d a3 ea cd 3c 89 43 4b |.....G.e....<.CK| +000000c0 36 28 4b b7 bc e4 93 93 ce 37 4c f5 63 ad 3b 3f |6(K......7L.c.;?| +000000d0 05 b9 92 56 88 35 89 30 5e 40 2d 46 ac 9d 1f ec |...V.5.0^@-F....| +000000e0 3d 0a 2a 32 d0 98 79 97 e2 93 2b b0 43 35 37 90 |=.*2..y...+.C57.| +000000f0 64 e3 a6 fd 09 01 14 61 17 03 03 02 6d 3c 5b ed |d......a....m<[.| +00000100 d8 cf c6 d9 e4 b1 7b 15 dc a1 c1 f6 88 87 1a 5c |......{........\| +00000110 22 37 53 87 a7 10 13 50 1c 1c 65 70 09 67 f3 63 |"7S....P..ep.g.c| +00000120 e7 63 88 76 50 45 e6 a8 1a 38 93 3b c0 ef fd c0 |.c.vPE...8.;....| +00000130 17 c2 c5 04 d6 15 c6 e9 70 bd d2 be 9a 38 50 8a |........p....8P.| +00000140 2b 4c a2 ea 4e ad 80 09 8f 24 2c 17 4d 17 e4 d8 |+L..N....$,.M...| +00000150 a1 47 13 fb 76 18 2d 04 8c 39 23 03 67 64 d2 d6 |.G..v.-..9#.gd..| +00000160 3d c8 4f 1d 1c 59 44 08 80 52 6e f3 3f 90 35 bc |=.O..YD..Rn.?.5.| +00000170 7e 58 1e 16 2c b0 7d 89 2a 4a a9 53 5a 2a ce 65 |~X..,.}.*J.SZ*.e| +00000180 c9 85 08 0b 6d e9 a4 9c e7 25 30 49 3c 85 bb 83 |....m....%0I<...| +00000190 7c 78 be 9d ee de 8f fb 01 d7 59 d5 4e 42 bc 21 ||x........Y.NB.!| +000001a0 e6 ba ed 0c 84 3c 8a aa 70 43 8a 46 c5 7f 81 65 |.....<..pC.F...e| +000001b0 b3 18 73 d9 73 8f 4e 67 5e 64 e3 92 0c 2f 03 e4 |..s.s.Ng^d.../..| +000001c0 81 ec 8a a2 0c 7d e9 97 5f 4b 5f 7e 55 48 24 8c |.....}.._K_~UH$.| +000001d0 ea d4 34 18 2b 88 6e 07 17 a9 7a be 6a 99 59 76 |..4.+.n...z.j.Yv| +000001e0 f5 1d 9b e9 4c ad f7 eb 94 8b bb 7d 93 46 ba a7 |....L......}.F..| +000001f0 d5 f8 3b 82 91 6d 5c 7e dc 0f da 08 19 06 40 f0 |..;..m\~......@.| +00000200 fd 16 68 24 fc 85 84 12 65 71 cf 91 63 46 ea 2f |..h$....eq..cF./| +00000210 d6 45 be 8a f3 27 0a 66 cb ed 8a d0 38 02 59 34 |.E...'.f....8.Y4| +00000220 4a 3d dc 6d 2d ef a4 f6 b4 c0 9d 29 85 b3 da 20 |J=.m-......)... | +00000230 4d 60 ec 90 eb 0f f1 5f 83 b4 bd 6a d5 0b b1 01 |M`....._...j....| +00000240 dd df a3 4c 1c b1 f6 b3 0c e0 8d 94 59 84 08 c4 |...L........Y...| +00000250 31 58 83 11 0b 04 5c 5e e3 ef 5a f4 6d 95 3a ca |1X....\^..Z.m.:.| +00000260 7a 11 b9 db e4 dd 38 66 65 b1 24 40 17 22 8f 90 |z.....8fe.$@."..| +00000270 f3 88 c6 a0 76 21 67 be 1f 6c aa ca ad c1 58 20 |....v!g..l....X | +00000280 dd c7 c0 20 32 a8 d7 db 9a 81 c9 82 38 a0 76 6b |... 2.......8.vk| +00000290 54 cf 79 cb 01 f1 59 50 3b 99 e2 68 96 2f 49 01 |T.y...YP;..h./I.| +000002a0 f6 7a ec a5 4f a0 91 be fb 85 52 ef 9b 6d 0c c1 |.z..O.....R..m..| +000002b0 36 82 a2 3f 0b 4e 4e 01 31 43 29 2a c0 26 41 83 |6..?.NN.1C)*.&A.| +000002c0 31 7b 9a b0 bf 0d 0f 96 b7 64 60 4d 07 2b 29 7e |1{.......d`M.+)~| +000002d0 d2 f6 c3 92 89 50 a7 19 b7 5b 15 6d 9c 0b 6e e3 |.....P...[.m..n.| +000002e0 01 d4 58 18 c0 22 95 e6 42 a7 1b 65 a8 2f 5f 6e |..X.."..B..e./_n| +000002f0 fc bc 00 ed 01 21 ec a9 6c ac 9e c7 c0 f0 f5 fc |.....!..l.......| +00000300 bd 0c c1 26 98 20 fa 1d a5 2a b6 fc 01 17 1c ba |...&. ...*......| +00000310 62 17 7d 39 25 76 bb 8c 77 5a bb 5e 74 22 f7 82 |b.}9%v..wZ.^t"..| +00000320 f1 65 8a 25 b5 05 53 db 84 de e6 59 1a a6 e7 09 |.e.%..S....Y....| +00000330 45 8e 14 fc e2 bc 9c 20 42 28 8d e2 ae 48 ad f4 |E...... B(...H..| +00000340 a0 ab 6b 3e 23 02 0a 0f ee 92 68 2f 29 1c 7e 4f |..k>#.....h/).~O| +00000350 8b 92 85 32 15 2f c1 dc fa 87 14 1d 21 3e 95 c6 |...2./......!>..| +00000360 e4 96 f1 66 d6 af bb eb d8 d4 17 03 03 00 99 31 |...f...........1| +00000370 1a 82 6b b3 f2 1d 12 83 7c df 15 6a 5b a8 af 96 |..k.....|..j[...| +00000380 a3 81 92 59 7a 19 c5 6b b4 ec e0 90 14 f1 00 ca |...Yz..k........| +00000390 0d d5 15 c5 24 49 a7 fc c2 2f 40 89 61 c1 6d d4 |....$I.../@.a.m.| +000003a0 da 39 f7 c3 42 50 e2 47 62 b2 5f 2b 91 70 e7 61 |.9..BP.Gb._+.p.a| +000003b0 57 e0 a3 20 a2 79 1f 18 ce f9 ad 5d ea 87 fa 16 |W.. .y.....]....| +000003c0 85 4b 50 a0 43 8f 0a 40 d7 93 cf 82 b5 82 6c 11 |.KP.C..@......l.| +000003d0 b7 cb 7c b2 4d 7d 23 ec a7 f8 2f b6 69 a8 83 29 |..|.M}#.../.i..)| +000003e0 4a ff 72 86 8e 05 79 91 a7 ed 4b 3d c8 86 fc 29 |J.r...y...K=...)| +000003f0 74 1e 88 7b a5 b2 2c 6e 62 08 2e a9 02 c9 05 d8 |t..{..,nb.......| +00000400 66 db 9c 28 35 79 ed 6f 17 03 03 00 35 24 4d e5 |f..(5y.o....5$M.| +00000410 81 c9 80 a9 1b c8 a9 20 27 c8 17 b3 0e 42 91 70 |....... '....B.p| +00000420 cb 4d ac 6f b8 b7 9a 96 94 95 fb ce f1 51 65 21 |.M.o.........Qe!| +00000430 ff 2c c5 53 42 1c b3 1c b1 9b 38 1a 1c a0 bf 3c |.,.SB.....8....<| +00000440 92 06 |..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 01 50 ef 68 27 d6 ec |..........P.h'..| -00000010 76 00 e1 c6 ed 3c f6 a1 83 b4 4b 26 28 ba 0f d6 |v....<....K&(...| -00000020 2a fd f0 4a 10 8f 9c ed 84 3f 0a 0e 5b 77 e2 7d |*..J.....?..[w.}| -00000030 1e 03 2a 76 5b 2b 87 78 ad bd 45 8b 03 b3 8d e7 |..*v[+.x..E.....| -00000040 b7 66 ca 5e 36 f8 53 87 90 3c 1a 33 46 1d 32 4f |.f.^6.S..<.3F.2O| -00000050 f1 90 fb 36 da 96 1c 1a db 9f 9b e6 9f 85 f8 13 |...6............| -00000060 7d e1 ab e1 ca c6 05 df 15 ea af dd 55 58 c7 5f |}...........UX._| -00000070 de 62 1b 93 60 a4 fc 39 0a ef 95 bc 0c ca 8f 84 |.b..`..9........| -00000080 98 0a 6d 5b fd c6 0c ad 02 7f 0c f8 b4 be fe 5a |..m[...........Z| -00000090 fb 22 00 08 09 5d c7 47 76 89 e5 06 d1 90 5b e6 |."...].Gv.....[.| -000000a0 63 64 06 28 37 d9 1b e9 0d 27 45 f7 72 30 d7 f2 |cd.(7....'E.r0..| -000000b0 db 8e bf 95 97 29 43 e7 16 bf a0 59 9c fa d9 59 |.....)C....Y...Y| -000000c0 a0 a6 9b 1f b5 74 80 87 d0 61 2f d5 a5 ac dd b2 |.....t...a/.....| -000000d0 8d 27 fc e6 68 eb 07 b3 3d 97 a9 93 5b 35 99 e9 |.'..h...=...[5..| -000000e0 ba 99 fe 49 d6 39 1a 0a 38 98 cd 47 b9 67 9b 9a |...I.9..8..G.g..| -000000f0 77 65 45 f8 48 fb d3 1c 0f a2 2e af e0 29 68 bc |weE.H........)h.| -00000100 81 24 3b 9b 36 0a ef 51 75 ff 61 6a d4 6c 59 42 |.$;.6..Qu.aj.lYB| -00000110 54 31 47 e9 02 9e 58 33 9e 89 65 b6 65 db b2 81 |T1G...X3..e.e...| -00000120 bd c1 f4 0a 34 eb f3 26 f5 8d 36 6d da 78 e6 88 |....4..&..6m.x..| -00000130 00 8f 92 24 dc 76 e3 95 dc 13 b5 92 91 ee c0 82 |...$.v..........| -00000140 cb 63 85 b6 59 67 dc 14 2e 2d 58 8e 56 7e 7c db |.c..Yg...-X.V~|.| -00000150 2f 54 01 ed 17 8d 9a 97 22 39 7f 17 03 03 00 59 |/T......"9.....Y| -00000160 a1 f2 0d 19 e7 d8 a8 6d cd ea f6 82 ee 5d 0a 55 |.......m.....].U| -00000170 22 61 11 21 f7 b0 1d 86 a8 4d c2 e2 9b ac bb 87 |"a.!.....M......| -00000180 a2 82 67 ee 78 76 9b e0 c0 00 85 bf 1e 2b ab e6 |..g.xv.......+..| -00000190 f1 43 79 69 a0 3d 04 b7 d9 7f 31 c7 7a b7 4f 5c |.Cyi.=....1.z.O\| -000001a0 9f 62 84 dc f4 6d a1 ce 3d ff 24 88 15 10 4a e6 |.b...m..=.$...J.| -000001b0 5c 12 68 08 3c 55 a2 a9 d7 17 03 03 00 35 f4 d9 |\.h..z....5=.| +000001c0 94 02 6e 65 f2 98 8d 45 3e d5 af 22 46 f0 70 3e |..ne...E>.."F.p>| +000001d0 d4 90 9c 02 0a f9 8d e6 c7 8f 52 af ab 74 67 12 |..........R..tg.| +000001e0 6d 8e 25 f8 03 73 02 78 5d 9c 8b 38 68 fe e9 96 |m.%..s.x]..8h...| +000001f0 c6 83 29 |..)| >>> Flow 4 (server to client) -00000000 17 03 03 01 c2 80 69 97 9a 20 30 2a 1c f4 31 f9 |......i.. 0*..1.| -00000010 0f cf f7 79 c0 01 e1 f3 35 f5 16 a0 33 d6 eb 21 |...y....5...3..!| -00000020 44 db bc c6 c4 91 6b a6 75 da ca d3 63 78 47 8b |D.....k.u...cxG.| -00000030 96 e5 6f 63 2c 77 c0 33 29 d8 3e ee bf 8e 6b d4 |..oc,w.3).>...k.| -00000040 de f7 1b 0e e6 ae ce cd 17 0d 24 77 10 3d e4 89 |..........$w.=..| -00000050 06 07 a3 77 68 ac 20 ec 0b ae 47 41 3b 80 4e 95 |...wh. ...GA;.N.| -00000060 02 aa 13 36 19 03 06 1c 47 b3 f7 f0 4b 6d 5a c6 |...6....G...KmZ.| -00000070 42 14 95 03 20 c7 46 96 42 d3 18 5a 40 bd a1 03 |B... .F.B..Z@...| -00000080 b6 d2 8b f9 ff 2d d1 b1 3c 8a 34 af 23 64 31 7d |.....-..<.4.#d1}| -00000090 46 47 21 b4 82 16 df a2 a4 0f 96 03 4b 38 3d 5d |FG!.........K8=]| -000000a0 d0 d1 78 d1 6e 6a a2 95 c0 a7 e6 ee 07 eb 77 68 |..x.nj........wh| -000000b0 35 78 72 3e df d9 4b e9 1b ab 34 99 2d fe 52 99 |5xr>..K...4.-.R.| -000000c0 6e 57 63 13 39 ae 5e ce b6 43 21 07 fd fe b7 6d |nWc.9.^..C!....m| -000000d0 8f 72 a4 f8 7e 0a 56 60 61 d5 5a d4 01 b3 47 8e |.r..~.V`a.Z...G.| -000000e0 f0 48 cd 85 61 a3 d2 d1 eb ba 04 39 6b 5e 5f fc |.H..a......9k^_.| -000000f0 e3 90 c1 cb 3f 40 30 00 5c 94 df bf 5b 89 6d ab |....?@0.\...[.m.| -00000100 15 1e 72 50 ac 56 ee 16 7d 84 4c e6 0c 89 68 fa |..rP.V..}.L...h.| -00000110 d5 8d 5f 09 85 25 5f 8c 70 df 0b b7 94 15 40 20 |.._..%_.p.....@ | -00000120 b1 ff 41 50 5d 9f c6 8a 9b 7f 40 6f dc bd 4f 54 |..AP].....@o..OT| -00000130 d8 1f e6 f1 44 00 11 97 45 ca 80 bc 15 eb 93 01 |....D...E.......| -00000140 dd 54 c6 75 7e 08 b9 38 f5 4d 97 c5 50 56 97 3c |.T.u~..8.M..PV.<| -00000150 3c 72 9a 33 7c 68 b1 73 2b 38 c7 b8 a8 3c 5d af |.....6....[..z| -00000170 f5 74 8d ac a4 0f 38 34 ee cd 08 50 e0 33 b0 e1 |.t....84...P.3..| -00000180 52 e1 5d f2 7d c6 7b 64 c7 46 f6 9e d0 a2 cf 89 |R.].}.{d.F......| -00000190 3c c9 ab 2f fb 8a f3 ba 78 e9 4c c5 2d 62 32 6b |<../....x.L.-b2k| -000001a0 50 4c a0 7e d3 bb 2a 66 57 99 38 69 e8 77 ef 18 |PL.~..*fW.8i.w..| -000001b0 24 af b3 cb e5 c0 37 a2 97 f6 00 d4 68 8a 71 af |$.....7.....h.q.| -000001c0 24 a4 ab 19 07 3b c0 17 03 03 00 1e 60 b4 fc 15 |$....;......`...| -000001d0 f9 9c b1 a1 60 1a ba f5 1b b9 c1 33 f1 8b e5 c0 |....`......3....| -000001e0 48 77 4f 11 42 21 ad 8c d2 d6 17 03 03 00 13 5c |HwO.B!.........\| -000001f0 db 07 5e 65 40 58 74 a4 7f ab 5f cc f0 9a 91 0c |..^e@Xt..._.....| -00000200 17 3d |.=| +00000000 17 03 03 01 c2 48 66 ba b6 48 e4 d9 1a 73 81 09 |.....Hf..H...s..| +00000010 cc 26 f8 2b bd 70 e7 15 c7 29 ac 30 58 21 ee 0c |.&.+.p...).0X!..| +00000020 9b c6 f0 b2 85 23 20 1a 7b ad ce fc 5f b6 ce aa |.....# .{..._...| +00000030 af a3 40 52 bf b3 3f 3d 61 a9 14 d1 eb 3c 21 78 |..@R..?=a......J.........| +00000170 fb ff 37 ce b7 5a 75 34 91 35 de 45 a2 36 71 05 |..7..Zu4.5.E.6q.| +00000180 20 65 d3 e4 fa 48 00 c1 25 3f f2 98 e8 0f 32 2a | e...H..%?....2*| +00000190 ee c5 60 f6 83 25 40 91 f6 13 0b fe 26 a9 f1 4c |..`..%@.....&..L| +000001a0 67 0d e8 c9 25 7e f5 f3 e3 ca 34 c3 e7 0e 4b e1 |g...%~....4...K.| +000001b0 c8 f4 40 94 69 88 a2 81 75 02 7d 6d d4 6a b3 c3 |..@.i...u.}m.j..| +000001c0 61 84 17 29 2a e9 90 17 03 03 00 1e 43 69 c6 7c |a..)*.......Ci.|| +000001d0 1a fa 1a cf bf 78 54 c0 8f b7 8d 83 d8 74 f9 54 |.....xT......t.T| +000001e0 6a 62 2f b1 68 63 69 b7 46 2e 17 03 03 00 13 08 |jb/.hci.F.......| +000001f0 49 af 4e 5f f1 e1 8a 7d 20 4e 55 2b 86 4f 03 a0 |I.N_...} NU+.O..| +00000200 d2 b5 |..| diff --git a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven index 8ba88ebf3fa..2a608bda261 100644 --- a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven +++ b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven @@ -1,177 +1,180 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 ca 01 00 00 c6 03 03 56 2e 3c 64 35 |...........V.>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 7c d3 26 20 |........... |.& | -00000030 a0 dc e9 7a 07 71 02 2d 3b 27 85 16 fb 6e 26 e5 |...z.q.-;'...n&.| -00000040 c3 67 e5 0b bd e5 50 8f bd 39 6f 2c 13 01 00 00 |.g....P..9o,....| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 b9 21 2b 29 |........... .!+)| +00000030 79 05 38 92 c6 fe 41 fa be d7 98 08 0a e4 12 b7 |y.8...A.........| +00000040 7a ea 10 5a 0d 1a f2 b4 81 5d 9d 01 13 01 00 00 |z..Z.....]......| 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| -00000080 03 03 00 01 01 17 03 03 00 17 43 8e 41 a4 04 13 |..........C.A...| -00000090 01 08 9f 6e 1a fd 00 68 38 5c 93 d9 9a f7 1e 36 |...n...h8\.....6| -000000a0 ea 17 03 03 00 3e 9f ae 80 ef f4 20 66 e7 44 fc |.....>..... f.D.| -000000b0 4d a4 3f 0e dc bb 33 47 0f 13 96 fa 03 07 d6 6f |M.?...3G.......o| -000000c0 cc 9f 3c fd 01 f5 87 d9 ec c9 d0 fc dd bf c8 5c |..<............\| -000000d0 0b 3d aa a7 c6 1d 90 18 d9 a1 1a a0 a1 ea 49 32 |.=............I2| -000000e0 9e 45 86 f7 17 03 03 02 6d 61 29 fe 45 7e 5c b3 |.E......ma).E~\.| -000000f0 8a 73 f2 65 c1 90 4e 93 0d 84 b2 bd e4 46 93 c2 |.s.e..N......F..| -00000100 52 3f 07 38 e7 23 db 25 5e 71 98 a9 7d fd e9 ef |R?.8.#.%^q..}...| -00000110 3f 2c d8 9c ae 41 c4 d3 c7 9e d5 6e f0 0c 33 78 |?,...A.....n..3x| -00000120 98 cf bf 22 3d 1f d0 f3 c8 a2 34 e8 ce 5e 0d 37 |..."=.....4..^.7| -00000130 52 e2 b8 e3 50 ea 35 3e e5 59 a0 6d ed 9e 09 36 |R...P.5>.Y.m...6| -00000140 59 20 33 08 a9 41 f4 72 aa 2d 0c b5 d6 96 d9 04 |Y 3..A.r.-......| -00000150 1a f1 d8 45 ed 67 ab f9 15 fa 25 ef 6d 87 72 ad |...E.g....%.m.r.| -00000160 f0 06 59 a5 8e 61 80 8b 28 f9 a0 df 5b b2 a2 3a |..Y..a..(...[..:| -00000170 1c 91 43 18 f4 a2 f3 4e db dc 24 1b c3 0e 77 22 |..C....N..$...w"| -00000180 83 ae 88 9f 8e 8d 48 38 f4 60 51 42 fa f2 a4 de |......H8.`QB....| -00000190 33 78 35 d0 b6 01 3d 7a f5 54 68 51 fd 0e 4c 9b |3x5...=z.ThQ..L.| -000001a0 92 7c a5 01 96 52 7e de 38 b9 b0 ee 60 1e aa eb |.|...R~.8...`...| -000001b0 8c e6 b4 f4 7c 35 d2 0b 9b 83 94 ac ac ce 7e 58 |....|5........~X| -000001c0 51 6e c3 ae 3b cd f5 85 8a 1e 43 78 19 ee dc a1 |Qn..;.....Cx....| -000001d0 a3 d0 93 24 0d 3b 6a 4b cd dc 78 9c 0b 2f bc 41 |...$.;jK..x../.A| -000001e0 46 2f 64 3c 23 95 04 8b 60 75 bf 4d 45 3b e4 1e |F/d<#...`u.ME;..| -000001f0 9c 5b 1a 46 bb f3 4d a9 1b 59 33 b4 40 78 bd ff |.[.F..M..Y3.@x..| -00000200 30 7d d4 cc 5e 83 03 de 8d a3 a6 27 b4 bc 12 6e |0}..^......'...n| -00000210 5e f2 88 e8 b6 60 f3 01 e8 4a 53 c7 a9 fc a1 cc |^....`...JS.....| -00000220 27 45 c1 06 90 38 9a fb 1b 2a 9e ed 9e f6 19 85 |'E...8...*......| -00000230 dd f7 8a 7f 95 08 3a 25 c0 5b 63 96 44 71 c2 16 |......:%.[c.Dq..| -00000240 9c e1 10 69 e5 6a 5c 4a e8 2a ed 6f bd de f5 98 |...i.j\J.*.o....| -00000250 c0 a0 c5 54 7c cc 06 11 b2 54 1a c3 b4 46 c2 b4 |...T|....T...F..| -00000260 97 d8 9c 7d f1 f3 d4 6f 3c a0 ef 18 c5 a6 e9 13 |...}...o<.......| -00000270 e9 f4 9d bf 9b 25 a2 da c6 ba 7a 6d 91 fd 41 a4 |.....%....zm..A.| -00000280 e8 88 e3 79 2c 99 df 4d 21 48 89 57 5a bf 2a 2d |...y,..M!H.WZ.*-| -00000290 72 4e 1e 3a e8 c9 82 7b c0 ff 6b 7c e8 8f 41 bf |rN.:...{..k|..A.| -000002a0 83 19 9e 96 d1 3f 2b 60 8f 7f 0b f8 6c 70 82 dd |.....?+`....lp..| -000002b0 34 da 91 62 17 20 e9 99 2e e2 a9 9a 9d fd 5d f8 |4..b. ........].| -000002c0 a5 c0 ac e8 a3 df 11 b5 df 2c bd e1 e8 0f 7e 0a |.........,....~.| -000002d0 f2 47 4c 92 33 7b 6b 49 e5 30 31 8b 2e 16 81 3e |.GL.3{kI.01....>| -000002e0 79 25 f7 d7 d2 8f 5e e6 e3 2d ed 0d e1 08 97 13 |y%....^..-......| -000002f0 f3 ce 7d b1 36 0d 7c b0 4f 23 6b 12 ef 3a a4 8b |..}.6.|.O#k..:..| -00000300 b5 d0 c9 ee 48 77 70 28 61 ff ad 49 f6 48 4c 37 |....Hwp(a..I.HL7| -00000310 7b 00 c4 01 5d 8b 54 bc 44 5c 5f 98 6f 7d 84 84 |{...].T.D\_.o}..| -00000320 c8 d0 55 88 f9 17 f6 02 f1 84 b6 3c 1a 03 e8 7b |..U........<...{| -00000330 b9 4e 24 c6 d8 0a f6 8c b9 49 c6 10 38 53 e1 10 |.N$......I..8S..| -00000340 8f 91 cd 39 9a 3a e8 c7 10 f3 c3 91 84 3c 8c a6 |...9.:.......<..| -00000350 55 ab f4 f5 ab e7 17 03 03 00 99 e5 40 f6 35 34 |U...........@.54| -00000360 2d 42 3e 7f e1 51 26 56 50 4e 60 b0 2f 65 e3 cd |-B>..Q&VPN`./e..| -00000370 c7 08 0e 96 77 08 c7 f6 4f e6 70 90 bc 80 95 e7 |....w...O.p.....| -00000380 b2 df 98 83 94 4d 9e 5c 8a af d3 45 da e9 d7 fa |.....M.\...E....| -00000390 d8 d2 60 f8 b1 06 d9 27 64 45 4d e8 d3 07 8a bb |..`....'dEM.....| -000003a0 72 7a c6 71 00 7e 8b b0 2b 7d d0 f7 ab 1a bf d2 |rz.q.~..+}......| -000003b0 50 be a9 3a 0c 68 b8 48 9a 91 ee db 26 4d d3 66 |P..:.h.H....&M.f| -000003c0 5b 00 ef c3 cc b8 f2 4e 1e 51 c7 9b 34 3c e3 01 |[......N.Q..4<..| -000003d0 7f 75 4e 41 e4 56 34 ec 14 92 0f 1e 6d dd 51 9a |.uNA.V4.....m.Q.| -000003e0 e0 8b 33 54 df 77 1f ff d3 72 67 4c 62 16 b7 f8 |..3T.w...rgLb...| -000003f0 4f 8f f8 ee 17 03 03 00 35 b7 83 d2 27 a3 15 f2 |O.......5...'...| -00000400 75 55 aa 06 8c 5f c4 fa 0f 43 88 c9 c5 e3 c7 36 |uU..._...C.....6| -00000410 40 6b 35 0b 7e 60 a1 1e 48 ef 46 2c d6 e4 48 80 |@k5.~`..H.F,..H.| -00000420 91 b0 e5 3b c0 58 5d fe 5d bd 0a 6c 19 ea |...;.X].]..l..| +00000080 03 03 00 01 01 17 03 03 00 17 4d 00 8b d1 bc 63 |..........M....c| +00000090 c3 8c af c4 0f 2e 36 78 8d 2b 52 32 f6 2c 29 0e |......6x.+R2.,).| +000000a0 17 17 03 03 00 52 aa 37 4e 5d 56 9a 8d 72 e7 77 |.....R.7N]V..r.w| +000000b0 f1 b7 0c 0b be 7d 63 92 58 0f 09 d7 a0 36 12 75 |.....}c.X....6.u| +000000c0 c9 0d ec d8 44 b4 8f ad dd a1 84 58 3f 0a 7c 47 |....D......X?.|G| +000000d0 0b c1 6f 56 7a 90 bf 82 6d 29 22 8b b3 50 03 ea |..oVz...m)"..P..| +000000e0 18 96 5e f5 1b f0 67 7d 10 c8 3f a4 f5 44 84 b3 |..^...g}..?..D..| +000000f0 f3 af 3e f2 b3 93 a1 57 17 03 03 02 6d 54 0a b5 |..>....W....mT..| +00000100 be 3f e0 77 de 6f e3 d7 83 60 2e 17 94 77 fb e1 |.?.w.o...`...w..| +00000110 11 e8 8d 22 1a 7b ac 36 94 35 d5 29 e5 fa 9e 07 |...".{.6.5.)....| +00000120 62 87 34 f8 b4 c5 ae d5 ee 84 76 c8 fd 30 cf a8 |b.4.......v..0..| +00000130 b1 a4 fe 42 12 e1 36 80 05 76 e2 d2 04 2b 6e c7 |...B..6..v...+n.| +00000140 0d 7d dc 99 de 3d 62 41 2f 3c c2 78 22 ec 6f 37 |.}...=bA/<.x".o7| +00000150 ab 0d 03 22 fe fc f4 82 41 49 44 fd 0a 02 4a 79 |..."....AID...Jy| +00000160 bd 5b 40 63 46 58 cd 84 b6 cf 46 c3 31 68 38 2a |.[@cFX....F.1h8*| +00000170 cf e0 3f ee de 06 ee de f8 e8 3e 37 ab 92 a6 9b |..?.......>7....| +00000180 0a f3 a8 64 6a 81 86 5d ed e3 a2 8c d0 0f 09 1e |...dj..]........| +00000190 ba e9 b0 6f 6b 1e 32 be 03 de 97 81 e0 42 ad 6e |...ok.2......B.n| +000001a0 f6 af bd 12 7a 2f f4 41 63 c4 f4 6a 61 8c e5 d4 |....z/.Ac..ja...| +000001b0 60 99 f2 d5 92 54 2f 28 ee 3f 9b ab fa c1 51 9b |`....T/(.?....Q.| +000001c0 f5 6b d1 d6 6d b1 17 28 95 5f 3c cc e4 41 bf 9b |.k..m..(._<..A..| +000001d0 c5 6e 29 4b 39 f8 ad b0 fe 51 4c 2b 92 76 ce 22 |.n)K9....QL+.v."| +000001e0 ee 5c 9e ad 0e 50 12 3d 2a a0 7a 6d a1 63 18 f7 |.\...P.=*.zm.c..| +000001f0 f2 a0 2a b7 b6 c9 f3 60 54 47 a8 90 dd 90 7d c3 |..*....`TG....}.| +00000200 6e f8 58 1c 28 e7 21 b4 52 33 da 67 67 2b b1 51 |n.X.(.!.R3.gg+.Q| +00000210 b0 41 97 a3 1f 9b cd c8 28 63 c9 f5 e5 d1 a3 3f |.A......(c.....?| +00000220 ac 1c 39 2e 72 1b e5 16 4d 8c b1 6b 4c 35 07 e9 |..9.r...M..kL5..| +00000230 24 a4 98 fb 67 75 4b 76 b7 2d cc 35 d9 a4 db 74 |$...guKv.-.5...t| +00000240 96 56 96 e0 74 8e f9 4a 45 19 30 57 a0 22 27 a9 |.V..t..JE.0W."'.| +00000250 d9 34 d7 73 f0 16 87 e5 be 8e b3 d2 53 f2 9c 19 |.4.s........S...| +00000260 c1 0a df 07 e7 e8 30 fb 44 ac 34 13 2b 22 4c a2 |......0.D.4.+"L.| +00000270 00 da 45 fc 95 1f 83 a0 c9 fa b3 b9 16 95 83 0f |..E.............| +00000280 a9 fa ae 2f b7 bc a1 55 d2 ab 2d 31 af 39 c2 82 |.../...U..-1.9..| +00000290 f7 bf 9a 9a 5c e6 61 d7 f2 9c d0 b5 53 85 58 cf |....\.a.....S.X.| +000002a0 9d 2e 50 eb 46 a1 a4 a0 aa c4 44 66 f7 61 41 0f |..P.F.....Df.aA.| +000002b0 75 68 36 76 11 7d 1e d7 be 0f a4 7a a8 bb 9e 26 |uh6v.}.....z...&| +000002c0 a9 7b ea 30 14 51 37 78 58 2a 92 e2 2c d3 9e 27 |.{.0.Q7xX*..,..'| +000002d0 86 92 83 a0 bc e8 50 ed da 9c 06 f4 d8 3c d5 6c |......P......<.l| +000002e0 a5 3a cc 1a ce 00 55 30 20 74 ad 17 5c bd 98 2d |.:....U0 t..\..-| +000002f0 1f 11 e7 38 99 2d b4 fc 1c 42 c9 ae f1 af 46 3e |...8.-...B....F>| +00000300 67 13 d2 31 16 34 fd e9 26 7c dd bb a0 25 10 7d |g..1.4..&|...%.}| +00000310 ca 94 20 6a b9 10 b7 94 0d 26 31 46 f2 bf 45 a8 |.. j.....&1F..E.| +00000320 ed 8f 08 15 7d db dd 3a ad 45 9f bd 32 8d ff 80 |....}..:.E..2...| +00000330 c6 1f bf 57 5e a0 dc 74 3c 8a b3 8f 03 ef a1 ef |...W^..t<.......| +00000340 12 65 2c c3 16 4f bc 63 3b 62 ab fa ae 9f d1 84 |.e,..O.c;b......| +00000350 79 80 25 04 bc e0 f9 70 98 e1 8c 15 55 ba cf a3 |y.%....p....U...| +00000360 0a 24 64 8c 3a b2 b7 a8 04 c1 17 03 03 00 99 c0 |.$d.:...........| +00000370 87 16 ce 52 d1 e9 83 f3 46 02 91 89 a1 6d 24 17 |...R....F....m$.| +00000380 dc 6a 05 bb c2 fb bd 93 94 05 60 8c 6c 47 f6 4a |.j........`.lG.J| +00000390 d8 ad 42 99 8b 77 92 91 f3 58 1e 10 3b 59 b1 19 |..B..w...X..;Y..| +000003a0 55 2c 3b f2 5b f3 e5 67 b2 e1 9c a8 68 dd 0e b9 |U,;.[..g....h...| +000003b0 67 c4 61 63 b3 bc 15 7b d6 76 7d 44 42 46 57 96 |g.ac...{.v}DBFW.| +000003c0 b3 10 40 39 2b 8c d5 fa cf a0 32 c0 d5 1a aa 96 |..@9+.....2.....| +000003d0 95 3b d5 55 fe 06 d2 34 31 7c 29 95 86 ac 7e f5 |.;.U...41|)...~.| +000003e0 e6 6b 7d a6 b5 52 37 2d 02 56 b8 12 66 33 67 80 |.k}..R7-.V..f3g.| +000003f0 14 5f 78 b3 a3 bf fc 4f cb 16 82 4e f5 c4 1b a1 |._x....O...N....| +00000400 33 3e 6c ed df 7b 4d 0b 17 03 03 00 35 dd de ca |3>l..{M.....5...| +00000410 4d 9e 09 ba 14 09 72 72 23 9f 3c 7e 2c 46 e5 5e |M.....rr#.<~,F.^| +00000420 50 a2 21 02 f7 03 4b 76 ab 4c a8 0b a2 b3 9b 7a |P.!...Kv.L.....z| +00000430 fc b9 5d a2 ac 0b c3 55 15 b8 b8 23 2b 61 46 00 |..]....U...#+aF.| +00000440 1c 5c |.\| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 11 9e 9e cf 44 84 |..............D.| -00000010 df e7 23 47 2d 4e 85 fa f2 02 2a 79 4d 3a 3d df |..#G-N....*yM:=.| -00000020 48 95 2e d7 0d 3c d0 05 fc bf bb 23 0a 25 59 76 |H....<.....#.%Yv| -00000030 fd 04 f8 f0 81 88 85 9f 99 f0 55 91 9a 79 8a 39 |..........U..y.9| -00000040 f4 6e 49 92 be ed 1d d1 20 19 77 bc 55 9b b0 da |.nI..... .w.U...| -00000050 d1 c4 9f b5 2f 5c 1a 60 38 e1 92 9b f9 a1 97 6b |..../\.`8......k| -00000060 1b d0 d0 d0 05 7a 41 26 d4 6b 12 a0 b3 c6 33 13 |.....zA&.k....3.| -00000070 4f 74 10 d6 91 fb b0 69 46 46 ca de 7c 05 d6 62 |Ot.....iFF..|..b| -00000080 51 23 12 58 00 ff 25 8e c8 5f 54 85 f4 2f e9 f9 |Q#.X..%.._T../..| -00000090 f1 1e 32 b9 f1 a6 fb 90 9b a9 65 d2 c9 ea a7 1a |..2.......e.....| -000000a0 e8 c9 a8 bb 7e 3d 3f 03 62 fc f4 06 a4 a2 f7 41 |....~=?.b......A| -000000b0 60 f5 f1 df 3e d6 31 51 f4 dc b1 d3 60 4b 84 4f |`...>.1Q....`K.O| -000000c0 99 e2 9f b2 f0 d5 fd b2 f3 5c 24 5f 91 a6 94 cd |.........\$_....| -000000d0 37 61 91 4e cc ae cd c1 b5 cc 58 5f 9a 91 a1 13 |7a.N......X_....| -000000e0 23 42 8a c5 27 4c 66 32 69 9c 75 9f 2a ed 73 1d |#B..'Lf2i.u.*.s.| -000000f0 29 2e 36 50 34 b4 80 d2 08 e6 9f c6 3e da df 9f |).6P4.......>...| -00000100 e0 2a 08 88 47 b6 d3 ff f7 6c 6c 91 1a 8e 53 89 |.*..G....ll...S.| -00000110 53 6c b8 d7 83 37 ab 03 59 e6 4f 41 42 af d4 f9 |Sl...7..Y.OAB...| -00000120 ac 9d ae d1 77 f1 71 79 a0 16 c4 c7 b5 a6 a9 9f |....w.qy........| -00000130 59 da 55 fb c5 88 8c 13 04 c2 06 39 8f ae 7e ca |Y.U........9..~.| -00000140 99 ce cd aa 86 0a 00 bd 56 f1 98 d9 c8 d2 c1 c0 |........V.......| -00000150 df 16 c2 6f 78 da 66 3f cc 43 c7 38 33 1b 3b 5b |...ox.f?.C.83.;[| -00000160 f8 7e d8 b7 ef 4c 6d c7 f6 84 56 8d 76 f7 0d 83 |.~...Lm...V.v...| -00000170 94 e6 ad c5 f3 05 5c f4 17 69 d5 83 98 c3 43 8e |......\..i....C.| -00000180 9f a5 5c 7b 12 ea f4 1f 39 ce 0d 83 15 b1 e6 ce |..\{....9.......| -00000190 c1 35 9b 8c ec c6 d2 d7 f9 02 36 90 24 f4 3a 70 |.5........6.$.:p| -000001a0 ce bb 8d bb 4b b2 aa 64 f0 b5 c0 88 cc 06 e3 9c |....K..d........| -000001b0 f7 70 64 fd 5d 48 f5 c8 07 48 c2 09 c4 07 56 b9 |.pd.]H...H....V.| -000001c0 86 e9 d6 7b dc ac a5 00 2c 1d 80 8f 47 f2 c4 c7 |...{....,...G...| -000001d0 ab dc 7b 41 7b 3d 47 db 09 12 02 9f 1b 63 e7 cc |..{A{=G......c..| -000001e0 38 1d 33 56 e0 ae 63 7a 95 73 5f e6 da 13 53 49 |8.3V..cz.s_...SI| -000001f0 5f 69 e9 ff 86 26 bd 9a dd be 5c 75 e7 69 66 b4 |_i...&....\u.if.| -00000200 27 3f 79 d2 2e 8e 79 9e 89 42 58 20 a2 ca 8c 2a |'?y...y..BX ...*| -00000210 37 b8 99 81 66 3a 31 66 1a 95 4c 47 17 03 03 00 |7...f:1f..LG....| -00000220 99 66 08 07 06 6d 95 fe f1 72 2a 7c de 84 06 b0 |.f...m...r*|....| -00000230 3d d7 d1 6b 47 0e 4d fb 9e ab 55 f7 71 c5 5d 11 |=..kG.M...U.q.].| -00000240 cb c7 fb 45 90 9d 22 eb ec 03 d6 ce 8c 01 ff 81 |...E..".........| -00000250 a2 90 23 1d 7a f3 cb 16 76 a5 05 57 77 f6 af f0 |..#.z...v..Ww...| -00000260 29 6c 6c 39 9e 99 55 c0 38 c3 31 68 49 b3 bf cc |)ll9..U.8.1hI...| -00000270 31 e2 6d a4 4c e7 99 53 2f 31 3f 05 2c 7c 1b 10 |1.m.L..S/1?.,|..| -00000280 60 ce 8b 60 47 16 eb e5 8b be 1b 7a 95 b9 3c 60 |`..`G......z..<`| -00000290 1c d6 b5 13 5f ad b9 bb 13 dd d6 08 8e 70 cb 2a |...._........p.*| -000002a0 26 3e df ce 7c 21 e5 27 7e 27 ec 75 b6 47 a0 89 |&>..|!.'~'.u.G..| -000002b0 2e e1 3c ab 0d 72 90 d1 d5 07 17 03 03 00 35 82 |..<..r........5.| -000002c0 6b 48 4a 9a 63 16 07 8f b2 d3 4a 65 7d e0 c4 e8 |kHJ.c.....Je}...| -000002d0 27 3e ce 4a 0a c8 63 e0 f9 70 98 c0 6a 12 39 ec |'>.J..c..p..j.9.| -000002e0 e1 52 de 73 58 2d f0 7c bc 8d 41 16 be 89 a0 88 |.R.sX-.|..A.....| -000002f0 56 e5 ef f6 |V...| +00000000 14 03 03 00 01 01 17 03 03 02 11 79 f8 bd a7 4e |...........y...N| +00000010 90 84 77 6f d1 a8 95 67 b7 0b e2 7a 4e 16 e9 ca |..wo...g...zN...| +00000020 1c f3 31 df a8 0e 99 02 c0 09 68 de 6a bb c2 bd |..1.......h.j...| +00000030 19 10 30 65 e6 5d d1 43 e2 aa 81 ba ea 3d 30 9a |..0e.].C.....=0.| +00000040 bb a8 66 ef 91 d1 1d 4c cd 93 97 19 f5 b7 52 1f |..f....L......R.| +00000050 c3 4b f8 dd 2f 39 53 54 68 06 dd 90 c1 75 57 9a |.K../9STh....uW.| +00000060 d6 9d c5 79 36 f9 5e bc c6 9b b8 bd 3d 14 40 71 |...y6.^.....=.@q| +00000070 a8 db 5c a8 d0 28 f3 a6 c1 37 29 c1 38 3f a3 51 |..\..(...7).8?.Q| +00000080 29 5c 01 eb 5c 7e c7 09 e6 2b fd 48 6f 53 77 25 |)\..\~...+.HoSw%| +00000090 c8 55 bb fd 68 21 a4 f0 f8 0e 52 41 97 81 20 78 |.U..h!....RA.. x| +000000a0 5e b8 77 3e 4e 6c 0a b1 32 98 2e d4 58 dd 64 fa |^.w>Nl..2...X.d.| +000000b0 8a 3e ba ea 79 67 c1 01 97 d2 5c d6 09 81 57 b0 |.>..yg....\...W.| +000000c0 fa c3 b8 3d 91 ee 7e 06 47 a8 3e 7b 59 74 14 44 |...=..~.G.>{Yt.D| +000000d0 29 28 29 1f 52 00 b8 31 4f ae 60 d5 18 72 fb a7 |)().R..1O.`..r..| +000000e0 21 0f 79 73 d8 e2 5c 6b b7 aa 78 53 f0 83 b5 ec |!.ys..\k..xS....| +000000f0 89 fc d0 fd 84 2e f6 3b 65 1d ac fe e8 75 10 f6 |.......;e....u..| +00000100 52 01 7f 5a 67 6d 1c 1d 82 4d eb 9d 2f fa 54 4e |R..Zgm...M../.TN| +00000110 0f 05 c8 d0 c3 50 6b cb 15 f0 27 5e 1d 15 b4 60 |.....Pk...'^...`| +00000120 85 bc b0 0e 54 3a 10 54 f9 4c 43 db 57 74 96 4b |....T:.T.LC.Wt.K| +00000130 12 1c c8 1b 4c b7 d6 44 e7 df 95 9b 1d 28 cc d0 |....L..D.....(..| +00000140 20 a5 9f 28 5d da 20 1a 46 42 1c b5 88 81 6b 3e | ..(]. .FB....k>| +00000150 0f 7b 37 5f b8 8e e5 b8 57 3c e7 03 6f 4f be 83 |.{7_....W<..oO..| +00000160 5a 3a a9 46 c6 e9 42 68 4f 10 38 bc ba 4d 67 7b |Z:.F..BhO.8..Mg{| +00000170 19 9a b0 bd ce 9a 8f 21 ff eb 82 59 a6 2f 0a 0f |.......!...Y./..| +00000180 b2 eb 76 c0 e2 dc 3f f4 3b c5 26 d3 7e 8c ed c3 |..v...?.;.&.~...| +00000190 5d 0f 80 56 a0 07 76 88 4c ab 04 3c aa 8a 44 65 |]..V..v.L..<..De| +000001a0 a7 5a 7b 31 29 5f 41 b8 12 c0 c0 f1 cd 95 08 0e |.Z{1)_A.........| +000001b0 f7 89 a0 af 91 e6 52 14 5a 2b 39 c5 c6 4e b7 72 |......R.Z+9..N.r| +000001c0 93 e2 a7 6f 00 b4 57 9b 20 e4 90 b9 57 f0 67 40 |...o..W. ...W.g@| +000001d0 e3 87 7d f6 6b f6 87 91 7f f6 3b 99 f2 93 b3 35 |..}.k.....;....5| +000001e0 e7 d4 fe 7c 1c b7 08 4a 00 de 7c 6c 85 df 2d 37 |...|...J..|l..-7| +000001f0 3b 69 62 18 c6 f9 e0 e3 6e 1d 30 cd 35 7d 83 5c |;ib.....n.0.5}.\| +00000200 1d 0c d8 61 df 4b f3 20 77 81 b1 9e 5f 84 79 44 |...a.K. w..._.yD| +00000210 93 b6 30 60 2d 76 4e 6d 4d 18 3a 21 17 03 03 00 |..0`-vNmM.:!....| +00000220 99 30 99 a3 ff 5c 70 58 5a d7 f0 ec 97 a0 d9 b8 |.0...\pXZ.......| +00000230 9e 98 08 f6 ec 87 48 3b c6 46 c2 45 c4 29 ab 08 |......H;.F.E.)..| +00000240 f2 ee 94 4d 89 c9 19 b4 0d b0 f6 df f7 a5 8d 4b |...M...........K| +00000250 2f 53 62 b8 ee 4c 8a cf 81 be fb 7e 16 2f ec f3 |/Sb..L.....~./..| +00000260 03 49 18 93 dc d3 53 67 fc a2 03 f8 f6 ab 26 87 |.I....Sg......&.| +00000270 92 32 7c 06 1a 12 14 29 cf a2 43 e4 36 04 2c ad |.2|....)..C.6.,.| +00000280 68 ea 5f 5a d2 83 81 d7 96 7d 8c 2e 9a 98 14 56 |h._Z.....}.....V| +00000290 a7 a3 23 69 d5 fd 21 9e 2f 81 43 2b 8a ad 2e c9 |..#i..!./.C+....| +000002a0 50 a8 a5 5c 28 b3 a0 62 c0 95 78 92 f7 3b 7b c0 |P..\(..b..x..;{.| +000002b0 1c a9 29 c4 34 28 39 c4 0b ef 17 03 03 00 35 8d |..).4(9.......5.| +000002c0 35 f3 1d 55 34 aa 92 ff 8f e6 2e c2 9b 2f c6 c8 |5..U4......../..| +000002d0 29 69 66 08 db fb 6f b5 22 4e bf 62 35 43 6c 72 |)if...o."N.b5Clr| +000002e0 c6 2a c4 57 8c a9 42 2c b8 5e 82 25 b2 92 aa 82 |.*.W..B,.^.%....| +000002f0 77 5f a4 1f 17 03 03 00 13 cc 12 01 75 9c 9f d3 |w_..........u...| +00000300 3f 17 17 a8 b8 8b b3 ae dc f6 08 34 |?..........4| >>> Flow 4 (server to client) -00000000 17 03 03 02 83 ce c4 10 39 1a fe 62 a2 ff 27 6d |........9..b..'m| -00000010 b7 e3 1d d6 8e b8 a2 7e f5 30 87 35 16 41 fb 04 |.......~.0.5.A..| -00000020 3c 79 9e 02 9b 06 4c a7 ba 01 5b cf 94 bc c8 08 |.| -00000050 58 7d fe c1 e3 78 79 31 48 d2 74 c0 8d 17 97 6f |X}...xy1H.t....o| -00000060 30 bb 8a 2c 8c d4 76 3d 3f f0 20 24 3d 5a 21 0c |0..,..v=?. $=Z!.| -00000070 37 7b 14 45 e6 69 db ed 52 50 a0 77 e9 a2 84 59 |7{.E.i..RP.w...Y| -00000080 0c 96 c1 ad 48 ed 8d 9f 00 4d f2 15 86 71 c0 fa |....H....M...q..| -00000090 14 b9 77 cb 9f 04 d9 1b be da 68 8e 31 8f 25 14 |..w.......h.1.%.| -000000a0 f5 43 bd e5 6e c5 10 ab f7 68 22 7f c2 ba 5c a6 |.C..n....h"...\.| -000000b0 88 31 c0 a5 fb 63 05 95 52 b3 04 94 14 fe eb 0c |.1...c..R.......| -000000c0 53 a0 c2 bf ae 58 e3 f9 84 22 6b ca 95 33 12 80 |S....X..."k..3..| -000000d0 09 e2 97 b0 2b 4b ed fa 34 e1 5a b1 de 52 b1 2c |....+K..4.Z..R.,| -000000e0 a0 aa 11 d6 fa 07 e1 41 ed 36 9f 9a 1a 56 18 b0 |.......A.6...V..| -000000f0 ef e7 85 dc 5b 53 23 56 c2 ac 34 64 c8 9d 4b 49 |....[S#V..4d..KI| -00000100 6d 29 7e 4b 73 4f 0b 8e 30 86 87 ea cf 1c dd 62 |m)~KsO..0......b| -00000110 c0 a4 96 aa fe 41 e7 25 94 8e 08 b5 4d 42 26 d3 |.....A.%....MB&.| -00000120 ba 84 98 bf 27 2b d5 3d 37 b9 b1 b5 24 33 e3 4d |....'+.=7...$3.M| -00000130 3f 05 38 54 fe 2c 15 63 20 2e 70 c0 c6 da 0e 89 |?.8T.,.c .p.....| -00000140 b6 99 07 db e3 7c 3e 58 d0 a3 2b 50 c4 f3 21 92 |.....|>X..+P..!.| -00000150 62 e0 e9 b5 d4 7a 6b 23 a2 05 ef 9c f5 f5 05 57 |b....zk#.......W| -00000160 cd d4 4d 0a 2f 17 ca ac fc 9d 7e 60 ec 3c 80 8c |..M./.....~`.<..| -00000170 1f 99 da b7 f6 14 7a e1 86 76 50 8d f8 6b 92 24 |......z..vP..k.$| -00000180 f2 b7 82 fa 3c 9b 14 af 0f 37 40 ae 7f 10 f5 0a |....<....7@.....| -00000190 f2 0f 0f bd 01 b7 0a f7 b6 d0 7f cf bf e6 67 55 |..............gU| -000001a0 cc 36 af a6 d8 c4 ca 80 c7 af 35 ff 6e 83 56 30 |.6........5.n.V0| -000001b0 62 26 49 bb 1a 04 8b 39 10 7b 0f 09 19 2b 0f 95 |b&I....9.{...+..| -000001c0 08 9d c8 85 3b 5d 8c 97 16 ae cd 92 00 d5 3e 50 |....;]........>P| -000001d0 54 66 85 8f 42 9b 60 3d f8 99 ca c7 07 3b 51 18 |Tf..B.`=.....;Q.| -000001e0 d5 20 37 57 35 0a d8 c6 13 0f 48 94 8f 50 7d 0e |. 7W5.....H..P}.| -000001f0 5a f0 98 b2 5d 5f 46 fb ba 85 c8 4f ba 02 19 86 |Z...]_F....O....| -00000200 0b ef 4a 04 49 1f 06 cd be dc d5 32 74 14 d8 60 |..J.I......2t..`| -00000210 17 a5 b5 a2 70 8e b1 75 29 bc e0 02 e0 a2 1c 7b |....p..u)......{| -00000220 58 cd 96 69 84 0f 95 7b 78 3e 09 72 a6 e0 50 7e |X..i...{x>.r..P~| -00000230 76 b0 7b 44 11 9b b8 7e 7d 09 49 91 75 5b 9b 6f |v.{D...~}.I.u[.o| -00000240 42 a4 e6 54 4d c6 21 65 c4 64 7d c6 29 74 13 8d |B..TM.!e.d}.)t..| -00000250 69 5f 20 8c f1 88 e8 1e 2d c3 13 d5 f5 52 70 24 |i_ .....-....Rp$| -00000260 de ec 64 c7 00 3f 57 e2 3f c4 23 fe e9 65 e6 d9 |..d..?W.?.#..e..| -00000270 92 ae f0 2f 05 4d 01 72 be 0d 7d c0 f4 30 ac 69 |.../.M.r..}..0.i| -00000280 3c 7c c1 72 c1 b7 c4 c9 17 03 03 00 1e 73 8f 48 |<|.r.........s.H| -00000290 cf 34 35 31 9b 63 59 59 1b 23 e1 6b b2 3a 0f df |.451.cYY.#.k.:..| -000002a0 21 69 8e 73 1a 61 09 5b 82 c7 78 17 03 03 00 13 |!i.s.a.[..x.....| -000002b0 4f a0 ab 25 3f a4 85 9e 78 58 69 d2 2c c3 b6 df |O..%?...xXi.,...| -000002c0 32 4a 7f |2J.| +00000000 17 03 03 02 83 63 68 c7 ae a5 c2 03 56 49 d3 13 |.....ch.....VI..| +00000010 45 f0 de 02 20 70 1a cb a5 cc 6f fa 0e 4b 28 65 |E... p....o..K(e| +00000020 4f 6d 76 2e b0 61 cf fe be 43 82 02 44 06 e4 1e |Omv..a...C..D...| +00000030 91 0c 64 1b 0e 58 53 c0 15 84 e8 6a 23 64 a1 cb |..d..XS....j#d..| +00000040 cd af e6 98 c1 c2 10 23 2b dd 54 9c ff d8 11 af |.......#+.T.....| +00000050 41 0c 88 7b 77 5c 12 47 7e f9 61 97 d6 f4 65 a7 |A..{w\.G~.a...e.| +00000060 5e 9c 06 0e 8a 96 5a 4c 60 f9 ce fb 52 a6 61 44 |^.....ZL`...R.aD| +00000070 7a d1 41 54 10 51 b6 26 d4 18 fb 37 75 55 7f 18 |z.AT.Q.&...7uU..| +00000080 10 39 ea b1 f7 d5 8f 3a a4 e8 d8 be f5 2f c2 90 |.9.....:...../..| +00000090 1a dd bc d7 50 b7 0e 7e c8 71 88 8f a0 04 34 2d |....P..~.q....4-| +000000a0 6f 35 f5 3f 43 08 1d 28 c7 30 db 8e c0 6c cd 14 |o5.?C..(.0...l..| +000000b0 93 10 fc b4 58 43 92 6d a3 3c 2e 87 71 12 70 c5 |....XC.m.<..q.p.| +000000c0 ec f8 64 5a 28 ee 3c 67 05 f4 00 f8 16 11 a6 49 |..dZ(.`3e.^_.| +00000110 7b 16 78 d9 8d 2a 92 16 62 02 fc 27 ee 72 f4 2e |{.x..*..b..'.r..| +00000120 86 11 32 55 a2 9b b7 d3 3a 3b 87 be 28 8f 30 e7 |..2U....:;..(.0.| +00000130 c7 ca 34 51 e5 3b 96 55 c1 d2 b2 b1 4e 84 85 0c |..4Q.;.U....N...| +00000140 df d9 25 3e 29 b8 56 4a 32 b7 45 1a b3 05 c1 d6 |..%>).VJ2.E.....| +00000150 ca ac 13 74 59 b6 0d 03 14 f2 fa b7 05 c4 2f da |...tY........./.| +00000160 11 65 a4 89 06 c6 fd 2b 10 3c 13 3d 92 d5 6a 1c |.e.....+.<.=..j.| +00000170 c5 01 10 b5 1a 3d a0 a5 ea ef 11 74 8b 68 24 20 |.....=.....t.h$ | +00000180 04 58 68 e4 e3 69 b7 12 03 f1 4c dd 78 65 04 58 |.Xh..i....L.xe.X| +00000190 d9 85 45 39 d2 74 18 f7 5c b4 59 fc 08 fb e0 49 |..E9.t..\.Y....I| +000001a0 c6 73 e0 0d 18 05 6a 84 95 03 11 ad 73 1d 45 d3 |.s....j.....s.E.| +000001b0 d7 66 c9 14 14 f4 ed 39 a6 b2 bd 81 ac 23 c0 d9 |.f.....9.....#..| +000001c0 ba 6a 82 16 75 2f c1 31 4f 83 25 ce 87 fb 23 97 |.j..u/.1O.%...#.| +000001d0 a0 0d 7c c8 2d 35 ce a6 e8 76 65 cb 72 cc 95 fc |..|.-5...ve.r...| +000001e0 8c 65 eb f7 74 7f a6 fc 1e 03 05 cd dc 56 8d 3c |.e..t........V.<| +000001f0 09 0b 74 48 24 72 19 07 c0 c4 a3 32 28 15 33 45 |..tH$r.....2(.3E| +00000200 ef c6 02 f2 8d bf 39 a9 b9 41 bd 99 77 be 36 67 |......9..A..w.6g| +00000210 0e eb 62 2b fa cd c9 6e b8 59 d8 f9 2b dd 09 1e |..b+...n.Y..+...| +00000220 4c 4a 90 e5 d4 4c 54 10 b9 f1 e3 5a 88 4b 3f 30 |LJ...LT....Z.K?0| +00000230 c9 7c d5 be e5 b0 44 4f bb 41 7a 83 e2 47 0c 73 |.|....DO.Az..G.s| +00000240 28 b9 f2 c0 6c 28 0c 3c 3a cd 34 92 5c 13 f8 15 |(...l(.<:.4.\...| +00000250 88 5b 02 fa 65 fd 1c b9 c0 cc 78 17 37 cc 53 50 |.[..e.....x.7.SP| +00000260 0f 53 5e a0 fa 08 48 93 c2 4e 7d c1 f9 bb f7 6a |.S^...H..N}....j| +00000270 e0 0e 8b 14 1a 64 60 b6 67 3a 07 68 13 20 e1 8a |.....d`.g:.h. ..| +00000280 f2 7b 0d 25 c6 11 2f 9e 17 03 03 00 1e 1e a5 9c |.{.%../.........| +00000290 f5 56 23 e2 91 d8 e1 fd da 88 04 24 b5 66 79 06 |.V#........$.fy.| +000002a0 b2 3d e8 95 60 e1 86 2d 34 f4 c8 17 03 03 00 13 |.=..`..-4.......| +000002b0 2a c7 60 04 0d 2f b5 d7 d2 c2 f9 15 bf 26 d7 84 |*.`../.......&..| +000002c0 05 98 ee |...| diff --git a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedNotGiven b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedNotGiven index b839c958794..7a06770a578 100644 --- a/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedNotGiven +++ b/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedNotGiven @@ -1,103 +1,105 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 ca 01 00 00 c6 03 03 4a ea 7e 77 82 |...........J.~w.| -00000010 17 37 46 db 49 14 d2 41 e4 14 b0 46 20 9d 50 45 |.7F.I..A...F .PE| -00000020 d1 75 08 82 2b 8d bc 9a 75 e3 71 20 ce 77 9a 79 |.u..+...u.q .w.y| -00000030 98 24 bc 15 be ac 30 fe 66 35 ab 51 be bd b4 fa |.$....0.f5.Q....| -00000040 6f 53 1f e9 5f 54 58 75 ce 94 f9 47 00 04 13 01 |oS.._TXu...G....| +00000000 16 03 01 00 ca 01 00 00 c6 03 03 00 69 af 00 d0 |............i...| +00000010 54 e8 0e 25 4c 62 db 87 e1 af 15 9e cf 14 ac b6 |T..%Lb..........| +00000020 ce 8c 5a 65 99 f3 c0 48 2e b6 00 20 c4 bf 7a 0b |..Ze...H... ..z.| +00000030 d8 da 4f 37 b8 12 7c ff 2e 1e ac 80 d4 32 77 0f |..O7..|......2w.| +00000040 92 8c b4 76 53 57 ba 7d bb 15 78 c8 00 04 13 01 |...vSW.}..x.....| 00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| 00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| -000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 e0 |-.....3.&.$... .| -000000b0 64 7e 58 b6 e7 32 fc c9 d6 3e f7 e0 f5 6a 9c 3a |d~X..2...>...j.:| -000000c0 e6 8f 83 d7 1c 27 62 72 71 06 71 de 49 96 05 |.....'brq.q.I..| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 30 |-.....3.&.$... 0| +000000b0 a0 2a f8 e2 67 08 84 a8 c9 fc f8 de 0e fb 3c 0c |.*..g.........<.| +000000c0 59 10 2d 50 e9 cc d4 32 5c 86 e2 6e 0d ba 03 |Y.-P...2\..n...| >>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 ce 77 9a 79 |........... .w.y| -00000030 98 24 bc 15 be ac 30 fe 66 35 ab 51 be bd b4 fa |.$....0.f5.Q....| -00000040 6f 53 1f e9 5f 54 58 75 ce 94 f9 47 13 01 00 00 |oS.._TXu...G....| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 c4 bf 7a 0b |........... ..z.| +00000030 d8 da 4f 37 b8 12 7c ff 2e 1e ac 80 d4 32 77 0f |..O7..|......2w.| +00000040 92 8c b4 76 53 57 ba 7d bb 15 78 c8 13 01 00 00 |...vSW.}..x.....| 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| -00000080 03 03 00 01 01 17 03 03 00 17 d0 8f 0a 7e 6c 33 |.............~l3| -00000090 0b be 2a 24 0e fc af df 6e 7d ad 22 28 82 77 60 |..*$....n}."(.w`| -000000a0 3d 17 03 03 00 3e 8f 87 8f f1 5a f6 6f eb eb d9 |=....>....Z.o...| -000000b0 da aa fc 3c 6d ac 73 94 a3 13 5f fe 01 bb 75 eb |........| -000001f0 50 76 d6 79 39 e8 25 bc 3b d9 5a a4 a8 5e 08 6a |Pv.y9.%.;.Z..^.j| -00000200 1c 48 b1 11 f0 d9 b9 48 39 e1 23 db 41 8c bf bd |.H.....H9.#.A...| -00000210 20 27 7b 0c 89 10 1f b0 ae 70 18 9a 7f f2 b4 1d | '{......p......| -00000220 20 cd 6d 80 38 00 a4 33 de 22 ef f6 42 52 c7 66 | .m.8..3."..BR.f| -00000230 83 4a 67 18 6b a6 38 27 d3 40 cf a2 a9 3e 58 06 |.Jg.k.8'.@...>X.| -00000240 91 a7 36 08 29 10 4d 8f 1b f9 7c 5a 17 05 81 b9 |..6.).M...|Z....| -00000250 4b 60 48 40 49 73 63 8a ef 9f f2 9e 80 85 57 fa |K`H@Isc.......W.| -00000260 0a b8 72 83 f3 26 fa 07 ae d2 47 99 b5 a6 5d c5 |..r..&....G...].| -00000270 1e b5 fc ea 0f 17 f8 ba e2 5c 7d 59 70 53 2e 23 |.........\}YpS.#| -00000280 f7 55 75 cb de 82 dc ca b1 bf 3f 5f 7d 7d 92 3c |.Uu.......?_}}.<| -00000290 29 29 64 30 74 0a 01 0b c0 95 db 45 fe 20 be 38 |))d0t......E. .8| -000002a0 c5 87 b7 e4 a9 93 63 67 6b 9a 2f 24 9e 62 8f 1d |......cgk./$.b..| -000002b0 bd 8c 4a d4 b0 0f 95 2f 56 b2 1c e8 5a 58 81 2e |..J..../V...ZX..| -000002c0 b5 b5 b5 f2 1b 7f 6c 39 58 75 51 dc 83 2a 59 0b |......l9XuQ..*Y.| -000002d0 78 5e 22 7e af ee 59 af b9 8f dc 65 97 af a5 b5 |x^"~..Y....e....| -000002e0 b8 50 af 35 51 30 e7 0a 75 e2 d0 33 e2 fb f4 b1 |.P.5Q0..u..3....| -000002f0 99 cd 5f 72 6b a9 f8 85 a1 a5 19 7e 2b 91 01 19 |.._rk......~+...| -00000300 09 dd 88 6e a7 d6 54 57 cd ef d0 97 6a 68 d9 6e |...n..TW....jh.n| -00000310 52 38 ef a5 fa 84 63 70 f0 6d 64 ec 66 1a c9 b5 |R8....cp.md.f...| -00000320 78 ba 17 74 f4 b4 2b a2 fe 9a 7f 38 b8 5e 8b 56 |x..t..+....8.^.V| -00000330 a6 7b 2c 92 7f db 58 c8 fa f9 2d 6b 00 25 dc 0a |.{,...X...-k.%..| -00000340 aa 13 e8 40 f3 fd 47 23 f6 bf 1c 30 fc 91 18 95 |...@..G#...0....| -00000350 ac a8 82 3d f5 ef 17 03 03 00 99 7e 30 4f f1 00 |...=.......~0O..| -00000360 1e dd eb c6 54 d2 f5 f7 21 aa 6b b0 83 0c fa 8b |....T...!.k.....| -00000370 12 af ac 15 3e 54 b6 1c 85 9b 0c 80 02 d8 e3 5f |....>T........._| -00000380 36 57 64 fe 7a b8 31 d0 aa 59 f1 e6 af e0 27 c5 |6Wd.z.1..Y....'.| -00000390 b8 d8 2f ab e0 cc c3 02 18 73 30 36 b5 2a 0d 12 |../......s06.*..| -000003a0 a4 45 e6 c3 79 9f 54 cb 51 61 1a b8 aa 87 45 43 |.E..y.T.Qa....EC| -000003b0 8e 93 58 66 f2 97 cb 3b 44 df ae 93 17 de 22 99 |..Xf...;D.....".| -000003c0 3c b4 9d 21 a6 db 03 ce 7b fb 67 b9 6e fb ab 50 |<..!....{.g.n..P| -000003d0 f8 33 9f 20 a0 fb e9 54 bb 62 16 19 d6 df 8c fe |.3. ...T.b......| -000003e0 3d 63 42 7c b0 72 2b 0d 87 1e f7 7d bb 59 ba f5 |=cB|.r+....}.Y..| -000003f0 d6 e8 f3 57 17 03 03 00 35 9e 6f 39 92 2e 32 10 |...W....5.o9..2.| -00000400 03 cd f0 28 2c 1a 32 77 19 c8 39 38 60 0c 28 b7 |...(,.2w..98`.(.| -00000410 8c 3a d8 50 a1 44 e4 d6 c5 64 59 88 2d a4 23 c9 |.:.P.D...dY.-.#.| -00000420 26 d1 96 0c c9 5d da 84 3e 8a 7d fe 80 77 |&....]..>.}..w| +00000080 03 03 00 01 01 17 03 03 00 17 47 a8 92 ce cd bb |..........G.....| +00000090 b5 b2 f6 47 50 c3 e7 c4 44 59 20 07 13 9a ca 98 |...GP...DY .....| +000000a0 f5 17 03 03 00 52 b6 9d 37 b2 ed bf 53 10 e2 28 |.....R..7...S..(| +000000b0 09 25 e5 f1 f8 6d 10 99 f8 b0 b8 1d cd 5c 82 ff |.%...m.......\..| +000000c0 de fd 9d 8e 89 94 2e 7a 7f ed 30 80 7e f0 e5 ef |.......z..0.~...| +000000d0 13 06 7b cf 8f 91 c9 38 e0 77 52 80 0d 74 a2 28 |..{....8.wR..t.(| +000000e0 a7 73 cd 06 df c4 7e 04 ad 6e e3 44 04 86 98 95 |.s....~..n.D....| +000000f0 b7 2d 76 99 3e 8b cd 7c 17 03 03 02 6d cb e5 77 |.-v.>..|....m..w| +00000100 58 3e c2 74 44 db 85 f8 54 12 02 89 8d 2b 8d 24 |X>.tD...T....+.$| +00000110 2a c0 db 71 25 b8 23 a1 86 1a 09 66 8e 60 b9 58 |*..q%.#....f.`.X| +00000120 40 0f 72 34 95 e2 6b 7c 76 8a 85 e5 dd cd be 0a |@.r4..k|v.......| +00000130 1f a3 13 42 aa 58 d7 95 0a 69 fc 60 5a 4d 17 db |...B.X...i.`ZM..| +00000140 19 59 d3 86 04 3e c2 1b 93 76 68 27 53 ae 07 af |.Y...>...vh'S...| +00000150 47 4e e6 03 b8 fe 8e c5 06 f1 84 54 0c e5 24 be |GN.........T..$.| +00000160 83 43 1f da 1e 3e 7e a3 2f 2f 4d bc cd e5 a5 b5 |.C...>~.//M.....| +00000170 5d 66 e1 2a 9b 1e 76 6c be e7 9d f7 ed c5 1b e9 |]f.*..vl........| +00000180 91 39 18 30 22 b5 d8 71 66 4d 62 b8 6f 94 7f 5f |.9.0"..qfMb.o.._| +00000190 84 77 a2 b5 79 02 a1 44 6a 5c d2 39 c2 95 d6 8e |.w..y..Dj\.9....| +000001a0 49 36 91 97 2e 02 59 47 e8 fa 78 b9 a7 0e 41 f2 |I6....YG..x...A.| +000001b0 df 92 44 7b 59 8f 9c e9 c8 1b 0a 15 cf 1a fe 5a |..D{Y..........Z| +000001c0 b2 5a 9d 9c b2 0b 1e 48 03 a9 2b 73 df 9f dd b2 |.Z.....H..+s....| +000001d0 30 d1 ba bd 46 e6 50 30 ed e3 c5 f7 d8 96 d5 cc |0...F.P0........| +000001e0 d2 3a 39 3b f0 a1 f2 8e 29 c4 be e9 ee af cb 7b |.:9;....)......{| +000001f0 f6 7d c3 be 4e 20 6e 63 21 50 d5 34 9a b4 9c 7f |.}..N nc!P.4....| +00000200 95 22 15 e3 ad 12 c8 6a 9c 68 a3 c1 35 c1 e1 fa |.".....j.h..5...| +00000210 ce 15 ef 12 b5 50 5b d3 56 8a 24 b0 61 ca 67 1d |.....P[.V.$.a.g.| +00000220 60 12 b3 4b 42 6a 3d ba ef 80 b1 b9 74 cf ba e0 |`..KBj=.....t...| +00000230 95 5f 1a b9 c6 24 d7 c5 ec 96 3f 6c e8 13 39 66 |._...$....?l..9f| +00000240 da e6 49 39 dc ca bc 2a 50 10 cf 51 fe d0 eb 80 |..I9...*P..Q....| +00000250 9c 21 dc 9d ae 10 31 d6 9c 9b ac 3e d6 84 36 e6 |.!....1....>..6.| +00000260 76 a1 d2 86 2a a0 2b d8 91 ba c3 f0 17 f7 7a 69 |v...*.+.......zi| +00000270 0d d3 14 6f ca ba 33 d2 d0 2e 85 a9 d7 dc d2 4a |...o..3........J| +00000280 dc bf 88 68 73 4f b1 35 e0 36 3b ed bd f6 37 0b |...hsO.5.6;...7.| +00000290 07 32 a1 96 81 29 63 e1 38 4d 52 7c 5a d0 4c 6c |.2...)c.8MR|Z.Ll| +000002a0 dd 65 83 75 1d 9e bc e4 c8 e7 75 13 5f 71 11 87 |.e.u......u._q..| +000002b0 ea 4b f3 ee d2 fd 38 2a 88 a6 35 e4 a8 63 77 0e |.K....8*..5..cw.| +000002c0 5f 57 ac a6 a2 e7 43 3c 79 1a 2d c9 1d 5f 65 22 |_W....C.K.5.| +000003c0 29 1d 3e ba a0 91 22 0a 8a aa a3 f8 9b eb 77 fe |).>...".......w.| +000003d0 19 ac 2e a7 29 ab 8f 61 91 af 09 b1 3b b3 4b 69 |....)..a....;.Ki| +000003e0 e6 96 a3 05 46 db 28 9b 1d d0 79 71 3d 93 4e 66 |....F.(...yq=.Nf| +000003f0 5d f4 22 38 91 a1 30 c5 c3 b7 72 fa e6 91 d8 a4 |]."8..0...r.....| +00000400 e9 a0 47 cc 5a 87 5e 60 17 03 03 00 35 ce b7 6e |..G.Z.^`....5..n| +00000410 2c 11 dc d4 b8 e1 a4 4b d8 d6 09 1e fe e3 d3 d3 |,......K........| +00000420 52 be fc cc af 5d 73 45 db 1e 05 b6 b1 38 59 65 |R....]sE.....8Ye| +00000430 df 72 6d 7b af b5 7a 3d e1 8a 27 44 6e 72 25 04 |.rm{..z=..'Dnr%.| +00000440 7c 61 ||a| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 19 87 49 99 a6 d9 |............I...| -00000010 ed cd f7 7a 75 14 e1 26 41 d2 6e 5c 79 a6 be 7c |...zu..&A.n\y..|| -00000020 5d 9d 44 36 17 03 03 00 35 1b 51 a9 b1 ce 11 ed |].D6....5.Q.....| -00000030 95 47 34 b9 3d 2f 6e 27 b2 e5 31 54 7f e3 8a 11 |.G4.=/n'..1T....| -00000040 fd 54 75 2c b6 8a 56 25 00 29 a7 5f 7a 1e 16 be |.Tu,..V%.)._z...| -00000050 16 e3 86 3a 72 84 0e bc 40 ef fd ad 18 33 |...:r...@....3| +00000000 14 03 03 00 01 01 17 03 03 00 19 01 ab 91 41 25 |..............A%| +00000010 d3 52 97 b2 f8 4e 57 9d c5 d3 7d 34 c4 c3 44 93 |.R...NW...}4..D.| +00000020 79 a5 0c fe 17 03 03 00 35 ba 56 09 d8 9d 73 5e |y.......5.V...s^| +00000030 f4 f4 03 4d bf f7 e4 ab cc 83 26 28 cc 68 78 91 |...M......&(.hx.| +00000040 9f 6f f6 dc d5 34 e5 a5 e6 86 11 b3 71 89 70 25 |.o...4......q.p%| +00000050 8c 83 79 b7 c8 56 92 1d 98 c7 35 cd bb 56 |..y..V....5..V| >>> Flow 4 (server to client) -00000000 17 03 03 00 8b 69 2e 81 c4 4d 43 a6 1f 96 b7 8e |.....i...MC.....| -00000010 87 4a 9b be 48 3c 31 18 98 f4 8c 04 24 b2 52 96 |.J..H<1.....$.R.| -00000020 04 b5 12 7c 54 37 83 6d 51 42 c6 52 f4 a5 bc d3 |...|T7.mQB.R....| -00000030 d1 c8 29 ab 4f e4 02 da 74 ec 8e 13 ad 03 f3 e0 |..).O...t.......| -00000040 7f 44 58 6b c7 28 a5 6a 75 30 b8 b1 31 38 fe ba |.DXk.(.ju0..18..| -00000050 e7 27 ae b3 e7 cb 5e 78 24 82 03 61 ba ae dd 4c |.'....^x$..a...L| -00000060 c6 7b f3 45 cf 6f a8 dc 7d 5d 73 65 db ae dc 10 |.{.E.o..}]se....| -00000070 ff 32 dc 4c b4 5e dc ce 4c 34 37 83 a0 0c d5 20 |.2.L.^..L47.... | -00000080 f1 f6 81 42 bc 63 65 47 80 d0 d6 f3 08 aa e2 58 |...B.ceG.......X| -00000090 17 03 03 00 1e 85 84 f3 e4 0f a8 24 c0 fe fa 2c |...........$...,| -000000a0 8b 60 52 32 73 2b 95 e9 37 3d 1c bd 2f ee ff e2 |.`R2s+..7=../...| -000000b0 70 13 df 17 03 03 00 13 65 2b 11 5f 50 7c 11 eb |p.......e+._P|..| -000000c0 3b 06 75 23 28 13 ca 4a b5 fb dc |;.u#(..J...| +00000000 17 03 03 00 8b eb fd 9e 19 36 7f 54 7f 9f 5a 6b |.........6.T..Zk| +00000010 31 0e e8 ca f3 40 7d 74 0d 82 6f 97 41 fb 15 52 |1....@}t..o.A..R| +00000020 36 00 50 c3 c5 36 ea e3 8f ca 02 b1 de ed 61 8e |6.P..6........a.| +00000030 60 0a d8 cf 0a 7c 47 60 87 3f fa 00 6f 74 a8 42 |`....|G`.?..ot.B| +00000040 c1 8d df f7 4d 7c ac c0 52 7c c9 21 5c 45 32 3f |....M|..R|.!\E2?| +00000050 42 0d 75 64 76 93 18 29 a1 50 06 36 94 bb 1e 52 |B.udv..).P.6...R| +00000060 31 5b b7 32 9a b1 9f 59 30 8a da ff 93 4f c1 b3 |1[.2...Y0....O..| +00000070 e9 8d f2 ec 4a 7b 01 51 5e a2 9b ea 8d a8 53 bd |....J{.Q^.....S.| +00000080 db 94 88 73 3b 9f da 77 a8 de 11 55 7b 06 0f c6 |...s;..w...U{...| +00000090 17 03 03 00 1e 1b 76 21 ea fd a4 47 6e ec 6e 26 |......v!...Gn.n&| +000000a0 00 3e fc 2f 87 8f 4e ee 08 58 e7 cc 46 aa b7 8c |.>./..N..X..F...| +000000b0 c1 5d dd 17 03 03 00 13 dd ed 88 b0 f5 e8 17 f1 |.]..............| +000000c0 66 85 c4 f5 6b 47 7d 5f 19 21 7f |f...kG}_.!.| diff --git a/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES b/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES index d2ed2ee64e9..d80662d169a 100644 --- a/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES +++ b/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES @@ -1,93 +1,93 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 ca 01 00 00 c6 03 03 be 5b 8c 08 2b |............[..+| -00000010 26 a0 41 0f e3 4e b6 5c 9f 5d 53 04 67 4a 1d a2 |&.A..N.\.]S.gJ..| -00000020 26 3b 83 ab b4 7b c6 ec f8 a6 41 20 a6 de ad e2 |&;...{....A ....| -00000030 0c fd 02 99 11 51 c6 be e8 52 df 0b e2 b3 6f fe |.....Q...R....o.| -00000040 33 3e 2f 90 ac d2 e8 a2 53 8b d9 05 00 04 13 01 |3>/.....S.......| +00000000 16 03 01 00 ca 01 00 00 c6 03 03 1d 95 21 d3 93 |.............!..| +00000010 6b 69 ad 44 69 28 2d 2e 74 c3 77 24 86 82 52 91 |ki.Di(-.t.w$..R.| +00000020 a8 15 64 82 15 2e 02 f8 41 3d c5 20 87 ff 55 4c |..d.....A=. ..UL| +00000030 00 16 80 c2 f7 44 15 18 bc 00 81 d8 7b d8 2c 88 |.....D......{.,.| +00000040 cb 19 31 89 23 d0 82 be d8 7f a4 26 00 04 13 01 |..1.#......&....| 00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| 00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| -000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 31 |-.....3.&.$... 1| -000000b0 8e dd f4 7c cf 22 04 c1 c3 04 5c 24 49 db ae ab |...|."....\$I...| -000000c0 0a d0 42 e8 70 51 c7 4f 88 e2 4e 2e 0b 80 65 |..B.pQ.O..N...e| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 8d |-.....3.&.$... .| +000000b0 18 6e 7e 5a 97 58 25 0d 07 9e af 9c 9b bd 6f 92 |.n~Z.X%.......o.| +000000c0 e9 08 8f 92 55 28 d2 90 3f fe bc dd db b7 00 |....U(..?......| >>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 a6 de ad e2 |........... ....| -00000030 0c fd 02 99 11 51 c6 be e8 52 df 0b e2 b3 6f fe |.....Q...R....o.| -00000040 33 3e 2f 90 ac d2 e8 a2 53 8b d9 05 13 01 00 00 |3>/.....S.......| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 87 ff 55 4c |........... ..UL| +00000030 00 16 80 c2 f7 44 15 18 bc 00 81 d8 7b d8 2c 88 |.....D......{.,.| +00000040 cb 19 31 89 23 d0 82 be d8 7f a4 26 13 01 00 00 |..1.#......&....| 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| -00000080 03 03 00 01 01 17 03 03 00 17 cc d0 60 a1 dc d6 |............`...| -00000090 46 57 69 3d df 0e 0f 7f a8 34 2d 87 71 84 16 54 |FWi=.....4-.q..T| -000000a0 9d 17 03 03 02 22 cb 9c f9 3e a0 fd bf 07 03 7c |....."...>.....|| -000000b0 53 0c 15 22 0b 78 e5 02 36 e6 e7 6c 5b f9 aa 8d |S..".x..6..l[...| -000000c0 54 8e b1 15 d4 23 05 12 5e 6e 0f 0f 65 77 bf b5 |T....#..^n..ew..| -000000d0 32 28 0e 32 ca 9f 61 c3 37 23 87 e8 ec 19 1d ba |2(.2..a.7#......| -000000e0 ef f5 18 eb ba 49 2d 86 a6 d1 f7 c1 9e 67 10 9f |.....I-......g..| -000000f0 a1 d2 62 bd 4c 6c 5e a4 41 f6 1e fa fd e7 55 bc |..b.Ll^.A.....U.| -00000100 16 ad 91 91 de 03 86 d7 e1 88 87 ab 0e f4 f5 bb |................| -00000110 16 da 37 bb a4 ce 4e 6c 5f 88 41 f9 a2 90 9a 2d |..7...Nl_.A....-| -00000120 5c 14 d5 01 28 06 a9 20 a4 ae 92 17 c5 95 b1 dc |\...(.. ........| -00000130 02 a8 3f 3b a7 97 91 5a 4f 56 bb db b6 30 0d 80 |..?;...ZOV...0..| -00000140 35 ac 91 6f 4f ba 1e 10 c6 fc d2 ca 96 e4 9d 1f |5..oO...........| -00000150 2f 29 00 3a 11 b7 77 dd d5 ed 76 9f 67 a1 b1 0c |/).:..w...v.g...| -00000160 5d 34 34 eb 42 49 23 15 49 12 24 24 73 be a9 65 |]44.BI#.I.$$s..e| -00000170 99 b6 b4 3f 18 0c d1 32 26 eb 86 93 5c 0e e8 06 |...?...2&...\...| -00000180 fb d7 9f 0e d9 26 14 47 b8 e5 67 8c c8 cb 0c 55 |.....&.G..g....U| -00000190 61 70 a9 ce 0d 4e bf ca 40 9c e7 0d 2b 5d 54 b7 |ap...N..@...+]T.| -000001a0 5a 64 50 e6 a1 c9 fc 47 7d e7 0a 13 36 8d 70 eb |ZdP....G}...6.p.| -000001b0 68 65 e4 9b 9d 12 d1 d9 0d 32 72 59 0f 46 b2 e2 |he.......2rY.F..| -000001c0 21 ab 13 d4 ab f3 6e b6 44 16 b8 85 bb dc f4 f7 |!.....n.D.......| -000001d0 d6 ce 5c 9f c0 4c 28 8f 36 39 ec 29 c7 33 bd ea |..\..L(.69.).3..| -000001e0 2d 10 16 84 50 c5 18 5b 2c a3 99 bb 3b 0b 70 66 |-...P..[,...;.pf| -000001f0 72 9a 83 01 06 2a bf 4a 60 c5 5d 41 a1 f0 92 bb |r....*.J`.]A....| -00000200 3b 2a 1a 41 3a 57 c3 22 13 2c b4 7b 3e 47 52 ea |;*.A:W.".,.{>GR.| -00000210 79 8a bf ef 2e 2c f7 89 c7 36 5a df 38 c2 04 b6 |y....,...6Z.8...| -00000220 6f 96 cd 7c 01 b3 e3 cd 4a 83 56 40 06 58 8a 7c |o..|....J.V@.X.|| -00000230 8c 75 df b6 b8 76 63 71 89 72 0a 64 de 23 7d 50 |.u...vcq.r.d.#}P| -00000240 77 a8 f6 a0 81 9d e9 ed 81 5e 20 c8 9f 65 3c 95 |w........^ ..e<.| -00000250 cf ed 99 80 71 06 5e 00 46 0d 0c 22 b3 88 f0 c5 |....q.^.F.."....| -00000260 33 3e 13 6b f2 07 9c db 20 31 9c 8d ea d7 73 e8 |3>.k.... 1....s.| -00000270 00 e1 2b f4 c8 d7 34 37 4a 98 b9 4d 28 db 15 8a |..+...47J..M(...| -00000280 af 53 14 3b 02 54 a3 0b 5f 10 ff 5d 20 1c 19 ae |.S.;.T.._..] ...| -00000290 6b 8a 99 a5 8f e0 ac dd c1 ba 1f 85 56 a3 94 bc |k...........V...| -000002a0 79 03 5f d5 dd e1 8e 62 b7 82 fa 92 c3 d5 8a fc |y._....b........| -000002b0 6b 17 24 d9 af db 3d 9c 0f 51 82 3d a2 ec 5f 9c |k.$...=..Q.=.._.| -000002c0 dc 69 a5 ce db d8 8b 87 17 03 03 00 a3 69 cd 7b |.i...........i.{| -000002d0 9f ac ad 72 11 b2 5d ee 19 63 d0 35 12 6d 5e 3f |...r..]..c.5.m^?| -000002e0 81 a8 18 4a d4 09 f3 80 38 4a 31 08 3e a0 4c 78 |...J....8J1.>.Lx| -000002f0 48 08 e9 90 ba e7 2a b4 73 2e 2b 2b 15 60 ce 09 |H.....*.s.++.`..| -00000300 7d df 49 31 e1 9d ff 92 1d b4 af 2e 8c f8 a6 2e |}.I1............| -00000310 93 d7 b9 10 69 10 7f 04 0d 8d e2 37 09 a7 d0 2a |....i......7...*| -00000320 ac ea 51 49 50 1d 1c 54 7f b9 15 ad 8c 77 ef 1d |..QIP..T.....w..| -00000330 a6 59 a3 bf b2 53 f7 6c 21 92 e0 36 c5 0d 61 94 |.Y...S.l!..6..a.| -00000340 be 61 5e 77 25 35 df e4 5f 67 c1 c6 af 51 e4 ce |.a^w%5.._g...Q..| -00000350 c4 28 c5 4e bc f6 c6 ba 32 dc 8e c7 45 f3 4d a1 |.(.N....2...E.M.| -00000360 70 53 98 46 8f 39 c2 cc b7 fc f7 24 11 97 72 b3 |pS.F.9.....$..r.| -00000370 17 03 03 00 35 76 be b6 7a 3f e3 08 7a a2 65 25 |....5v..z?..z.e%| -00000380 fd 0b c3 87 be ba eb ca cb 3d c1 25 10 e0 7b 00 |.........=.%..{.| -00000390 37 7a 52 9e d6 b2 e7 ba 8e 51 de 15 c4 e8 16 eb |7zR......Q......| -000003a0 c6 21 92 42 b1 62 f4 ce 27 ba 17 03 03 00 8b 54 |.!.B.b..'......T| -000003b0 03 de d7 a7 85 2f 4b 23 2d d5 3a b4 3d 3d f6 00 |...../K#-.:.==..| -000003c0 ac ab bd 6f dd bf 9f 24 fb 1b d4 01 39 3e c0 87 |...o...$....9>..| -000003d0 bb 32 ca f6 61 b2 ef 5d 9c 2c 1b a5 10 66 7b fd |.2..a..].,...f{.| -000003e0 4b d0 03 dc 53 a9 0d 5a d5 c4 4c 25 9c 55 e6 f8 |K...S..Z..L%.U..| -000003f0 d1 d8 49 dc 36 a1 92 ae f1 3e 2f 11 66 87 93 69 |..I.6....>/.f..i| -00000400 24 2e 5d 6c f6 79 15 68 a8 99 2e 1a 9c e2 85 4e |$.]l.y.h.......N| -00000410 5f d6 a8 3c 70 e1 67 cb df b2 1b ab 2b ed dc b6 |_....b...O| +000000a0 e8 17 03 03 02 22 3f 87 53 63 dc 59 f7 32 60 4b |....."?.Sc.Y.2`K| +000000b0 bd 9f e1 fc 4c 9a 98 18 94 e1 c1 07 ab 11 33 dc |....L.........3.| +000000c0 f1 48 67 e6 66 83 3c 88 53 c7 dc af e2 87 bc 0b |.Hg.f.<.S.......| +000000d0 d7 60 99 83 29 a1 1c 30 09 ba 4a e1 a9 c2 0e 34 |.`..)..0..J....4| +000000e0 cb a6 f2 8b 1b a0 b0 e6 21 27 3d b8 b4 90 0c 61 |........!'=....a| +000000f0 af 38 db fe fe 9c 34 09 1e 1a c8 f2 e9 05 68 ee |.8....4.......h.| +00000100 9c ec 74 b8 10 25 29 3d 52 71 87 c6 88 22 5a e9 |..t..%)=Rq..."Z.| +00000110 33 d0 d3 75 a8 94 b2 6d 48 4f 63 d1 32 f2 a3 70 |3..u...mHOc.2..p| +00000120 f1 a5 0b 4c 5d 7c 91 9b 04 d4 c3 9e 37 dd 67 a1 |...L]|......7.g.| +00000130 aa 23 6f 2b d0 42 b9 30 5c ed ae 12 36 f1 7c b3 |.#o+.B.0\...6.|.| +00000140 92 de 02 3a 99 c3 98 91 a3 09 43 ef 24 8d 67 e7 |...:......C.$.g.| +00000150 0d 68 22 e1 cc 99 8e 8e 64 09 be 50 f7 4a 37 0a |.h".....d..P.J7.| +00000160 02 af 88 db 8b a0 68 0d 7e 97 d9 9c 48 c3 bd aa |......h.~...H...| +00000170 db 01 69 2b 2b e6 f5 4b 66 c0 7a 8c fe 4d 8f 7b |..i++..Kf.z..M.{| +00000180 94 be 58 b5 44 67 df 26 3f 79 ee 55 bf bf aa 52 |..X.Dg.&?y.U...R| +00000190 95 ec 6b 7f 2b 68 f0 5a 81 4e 13 25 91 bd 9a df |..k.+h.Z.N.%....| +000001a0 dd 2c ae 6d c3 47 27 c2 3f 51 98 a3 b7 06 ec 2f |.,.m.G'.?Q...../| +000001b0 d6 c0 7f 1f e5 5e 3c 50 d3 6e 82 33 be 07 48 0b |.....^..}.....HUB..| +00000260 d0 b2 8e 4d c6 26 bb 77 9e 3f e0 0a 90 a4 3b eb |...M.&.w.?....;.| +00000270 37 94 c4 e8 39 12 82 24 b3 8b 6d 0d ed 9c 31 f0 |7...9..$..m...1.| +00000280 d0 5a cb b0 79 9b d2 ed ab 08 8b 9d ad 25 7a ce |.Z..y........%z.| +00000290 d7 6d c8 11 0a 60 f4 81 e9 e3 e3 42 7b 3d 95 67 |.m...`.....B{=.g| +000002a0 c2 4e 3e 80 11 2e 09 53 94 03 c0 88 cb 23 7e d2 |.N>....S.....#~.| +000002b0 ad e2 dc e7 e2 0b ba 74 9c 04 ad 75 e6 7f 5a fb |.......t...u..Z.| +000002c0 53 5a 98 14 18 4f 1d 2b 17 03 03 00 a4 7a ce c7 |SZ...O.+.....z..| +000002d0 9c de bc 27 04 f7 8b 4b a1 73 7d 0d fa b5 a1 e2 |...'...K.s}.....| +000002e0 fe 8b 33 8d 48 64 65 13 68 e2 5d e2 d7 3e 67 f2 |..3.Hde.h.]..>g.| +000002f0 db bd ff f9 e5 3e 4c b1 56 e3 22 95 88 23 48 fe |.....>L.V."..#H.| +00000300 0f 80 4c 5c 1c 74 0e 26 d4 7c 17 83 65 d6 a3 51 |..L\.t.&.|..e..Q| +00000310 5a 01 a5 12 9c db 0b c9 0b 8b 53 c7 03 75 b9 04 |Z.........S..u..| +00000320 a0 62 df 11 75 ae ff 33 7b 98 6b 7b 35 3e 41 4c |.b..u..3{.k{5>AL| +00000330 9b 16 12 b4 39 ce 9a d5 e9 83 78 b3 4b 3e d6 82 |....9.....x.K>..| +00000340 75 66 bf 73 e4 26 e6 22 8e 2f fe 4d 49 e4 b5 03 |uf.s.&."./.MI...| +00000350 04 a6 65 59 c2 aa e2 e6 ec f0 e2 99 b5 c4 55 75 |..eY..........Uu| +00000360 e1 90 a4 73 cb 21 78 df 4e 96 e2 99 75 15 77 59 |...s.!x.N...u.wY| +00000370 db 17 03 03 00 35 bc 1c 15 d7 b0 62 21 d4 dd 09 |.....5.....b!...| +00000380 1d aa 05 3c e3 ea 0a 9d 89 1f aa 2f f7 75 93 86 |...<......./.u..| +00000390 35 ee 5f 06 20 99 17 ca 4c 05 65 07 f7 56 9f 62 |5._. ...L.e..V.b| +000003a0 2a ea e2 05 f0 be fe bf d6 09 46 17 03 03 00 8b |*.........F.....| +000003b0 37 1a 6c e5 ea 27 e7 b2 d7 87 9a 1a a1 41 b5 64 |7.l..'.......A.d| +000003c0 61 8b bb 1c 64 a2 37 de 39 b3 5b f4 5b 9f bf d8 |a...d.7.9.[.[...| +000003d0 e7 3d be ad 96 6c 69 19 ce 8e a8 12 14 5d 1e 79 |.=...li......].y| +000003e0 c5 12 53 c3 13 81 5a 22 44 e5 6e c4 97 cc 18 19 |..S...Z"D.n.....| +000003f0 c4 04 08 cf 16 dd df 3d 4f 13 40 5f 33 38 f5 0f |.......=O.@_38..| +00000400 4f bb 41 e2 85 85 43 de d0 b5 7a 61 d8 3a 53 41 |O.A...C...za.:SA| +00000410 d2 ad 7b e4 bf 02 d2 14 7d f7 0c 05 b8 bb 21 90 |..{.....}.....!.| +00000420 a5 61 76 7e 07 5d bf e2 a1 f8 1a a6 77 42 2a 7c |.av~.]......wB*|| +00000430 7a 41 a7 5e 04 c2 49 02 45 a8 f5 |zA.^..I.E..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 46 8b fa 42 0d |..........5F..B.| -00000010 fa 3e 9e 80 76 12 ce 73 ae 85 67 ee af 1e 25 6e |.>..v..s..g...%n| -00000020 0b 46 4c bd 5a 46 8e 5c 27 7a 0a 8d d3 9c 3c 29 |.FL.ZF.\'z....<)| -00000030 4c c8 08 78 ac 9f f4 7a 38 8d 49 6a 01 b6 f5 83 |L..x...z8.Ij....| +00000000 14 03 03 00 01 01 17 03 03 00 35 3d f2 27 fe 81 |..........5=.'..| +00000010 4c 6e 61 1f 34 f8 3d 25 1f 33 d6 22 aa 7f ab 08 |Lna.4.=%.3."....| +00000020 2c 48 44 39 74 2c e9 be 78 7f c7 db 27 b0 b0 6d |,HD9t,..x...'..m| +00000030 b2 8b 87 6c e5 5c 38 79 9f ed 3d 4f 92 81 dc ea |...l.\8y..=O....| >>> Flow 4 (server to client) -00000000 17 03 03 00 1e c2 1a dc 0a cb 9a 11 f7 a1 c2 1f |................| -00000010 54 7d 32 6f 0e 13 b6 6b 9f e1 c6 14 63 fc 18 b9 |T}2o...k....c...| -00000020 81 53 44 17 03 03 00 13 c9 72 ae 5e 2b c1 6f 64 |.SD......r.^+.od| -00000030 e0 70 47 15 b1 ec c3 25 00 7f 4e |.pG....%..N| +00000000 17 03 03 00 1e f7 99 f9 d8 a2 00 d9 e3 48 d9 b2 |.............H..| +00000010 35 37 93 6f b0 1f d5 81 b1 16 b1 e4 d8 b4 40 ce |57.o..........@.| +00000020 97 9f 16 17 03 03 00 13 a4 cb 62 61 70 e9 67 c3 |..........bap.g.| +00000030 21 02 19 bc 01 01 5d 9b 15 d4 84 |!.....]....| diff --git a/crypto/tls/ticket.go b/crypto/tls/ticket.go index ae4176773ff..051f28d54ad 100644 --- a/crypto/tls/ticket.go +++ b/crypto/tls/ticket.go @@ -45,20 +45,21 @@ type SessionState struct { // case 0: Empty; // case 1: opaque alpn<1..2^8-1>; // }; - // select (SessionState.type) { - // case server: Empty; - // case client: struct { - // select (SessionState.version) { - // case VersionTLS10..VersionTLS12: Empty; - // case VersionTLS13: struct { - // uint64 use_by; - // uint32 age_add; - // }; + // select (SessionState.version) { + // case VersionTLS10..VersionTLS12: uint16 curve_id; + // case VersionTLS13: select (SessionState.type) { + // case server: Empty; + // case client: struct { + // uint64 use_by; + // uint32 age_add; // }; // }; // }; // } SessionState; // + // The format can be extended backwards-compatibly by adding new fields at + // the end. Otherwise, a new SessionStateType must be used, as different Go + // versions may share the same session ticket encryption key. // Extra is ignored by crypto/tls, but is encoded by [SessionState.Bytes] // and parsed by [ParseSessionState]. @@ -84,21 +85,23 @@ type SessionState struct { // createdAt is the generation time of the secret on the sever (which for // TLS 1.0–1.2 might be earlier than the current session) and the time at // which the ticket was received on the client. - createdAt uint64 // seconds since UNIX epoch - secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3 - extMasterSecret bool - peerCertificates []*x509.Certificate - activeCertHandles []*activeCert - ocspResponse []byte - scts [][]byte - verifiedChains [][]*x509.Certificate - alpnProtocol string // only set if EarlyData is true + createdAt uint64 // seconds since UNIX epoch + secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3 + extMasterSecret bool + peerCertificates []*x509.Certificate + ocspResponse []byte + scts [][]byte + verifiedChains [][]*x509.Certificate + alpnProtocol string // only set if EarlyData is true // Client-side TLS 1.3-only fields. useBy uint64 // seconds since UNIX epoch ageAdd uint32 ticket []byte lifetime uint32 + + // TLS 1.0–1.2 only fields. + curveID CurveID } // Bytes encodes the session, including any private fields, so that it can be @@ -163,11 +166,13 @@ func (s *SessionState) Bytes() ([]byte, error) { b.AddBytes([]byte(s.alpnProtocol)) }) } - if s.isClient { - if s.version >= VersionTLS13 { + if s.version >= VersionTLS13 { + if s.isClient { addUint64(&b, s.useBy) b.AddUint32(s.ageAdd) } + } else { + b.AddUint16(uint16(s.curveID)) } return b.Bytes() } @@ -189,7 +194,6 @@ func ParseSessionState(data []byte) (*SessionState, error) { var extra cryptobyte.String if !s.ReadUint16(&ss.version) || !s.ReadUint8(&typ) || - (typ != 1 && typ != 2) || !s.ReadUint16(&ss.cipherSuite) || !readUint64(&s, &ss.createdAt) || !readUint8LengthPrefixed(&s, &ss.secret) || @@ -207,6 +211,14 @@ func ParseSessionState(data []byte) (*SessionState, error) { } ss.Extra = append(ss.Extra, e) } + switch typ { + case 1: + ss.isClient = false + case 2: + ss.isClient = true + default: + return nil, errors.New("tls: unknown session encoding") + } switch extMasterSecret { case 0: ss.extMasterSecret = false @@ -228,8 +240,10 @@ func ParseSessionState(data []byte) (*SessionState, error) { if err != nil { return nil, err } - ss.activeCertHandles = append(ss.activeCertHandles, c) - ss.peerCertificates = append(ss.peerCertificates, c.cert) + ss.peerCertificates = append(ss.peerCertificates, c) + } + if ss.isClient && len(ss.peerCertificates) == 0 { + return nil, errors.New("tls: no server certificates in client session") } ss.ocspResponse = cert.OCSPStaple ss.scts = cert.SignedCertificateTimestamps @@ -256,8 +270,7 @@ func ParseSessionState(data []byte) (*SessionState, error) { if err != nil { return nil, err } - ss.activeCertHandles = append(ss.activeCertHandles, c) - chain = append(chain, c.cert) + chain = append(chain, c) } ss.verifiedChains = append(ss.verifiedChains, chain) } @@ -268,24 +281,16 @@ func ParseSessionState(data []byte) (*SessionState, error) { } ss.alpnProtocol = string(alpn) } - if isClient := typ == 2; !isClient { - if !s.Empty() { - return nil, errors.New("tls: invalid session encoding") + if ss.version >= VersionTLS13 { + if ss.isClient { + if !s.ReadUint64(&ss.useBy) || !s.ReadUint32(&ss.ageAdd) { + return nil, errors.New("tls: invalid session encoding") + } } - return ss, nil - } - ss.isClient = true - if len(ss.peerCertificates) == 0 { - return nil, errors.New("tls: no server certificates in client session") - } - if ss.version < VersionTLS13 { - if !s.Empty() { + } else { + if !s.ReadUint16((*uint16)(&ss.curveID)) { return nil, errors.New("tls: invalid session encoding") } - return ss, nil - } - if !s.ReadUint64(&ss.useBy) || !s.ReadUint32(&ss.ageAdd) || !s.Empty() { - return nil, errors.New("tls: invalid session encoding") } return ss, nil } @@ -294,17 +299,17 @@ func ParseSessionState(data []byte) (*SessionState, error) { // from the current connection. func (c *Conn) sessionState() *SessionState { return &SessionState{ - version: c.vers, - cipherSuite: c.cipherSuite, - createdAt: uint64(c.config.time().Unix()), - alpnProtocol: c.clientProtocol, - peerCertificates: c.peerCertificates, - activeCertHandles: c.activeCertHandles, - ocspResponse: c.ocspResponse, - scts: c.scts, - isClient: c.isClient, - extMasterSecret: c.extMasterSecret, - verifiedChains: c.verifiedChains, + version: c.vers, + cipherSuite: c.cipherSuite, + createdAt: uint64(c.config.time().Unix()), + alpnProtocol: c.clientProtocol, + peerCertificates: c.peerCertificates, + ocspResponse: c.ocspResponse, + scts: c.scts, + isClient: c.isClient, + extMasterSecret: c.extMasterSecret, + verifiedChains: c.verifiedChains, + curveID: c.curveID, } } @@ -400,7 +405,7 @@ func (c *Config) decryptTicket(encrypted []byte, ticketKeys []ticketKey) []byte // resume a previous TLS session. type ClientSessionState struct { session *SessionState - // zcrypto + // excrypto preMasterSecret PreMasterSecret sessionTicket SessionTicket lifetimeHint uint32 diff --git a/crypto/tls/tls.go b/crypto/tls/tls.go index 357378f4436..19b4ef67db3 100644 --- a/crypto/tls/tls.go +++ b/crypto/tls/tls.go @@ -4,6 +4,18 @@ // Package tls partially implements TLS 1.2, as specified in RFC 5246, // and TLS 1.3, as specified in RFC 8446. +// +// # FIPS 140-3 mode +// +// When the program is in [FIPS 140-3 mode], this package behaves as if only +// SP 800-140C and SP 800-140D approved protocol versions, cipher suites, +// signature algorithms, certificate public key types and sizes, and key +// exchange and derivation algorithms were implemented. Others are silently +// ignored and not negotiated, or rejected. This set may depend on the +// algorithms supported by the FIPS 140-3 Go Cryptographic Module selected with +// GOFIPS140, and may change across Go versions. +// +// [FIPS 140-3 mode]: https://go.dev/doc/security/fips140 package tls // BUG(agl): The crypto/tls package only implements some countermeasures diff --git a/crypto/tls/tls_handshake.go b/crypto/tls/tls_handshake.go index b6bc37ba210..cfe8fa89c61 100644 --- a/crypto/tls/tls_handshake.go +++ b/crypto/tls/tls_handshake.go @@ -436,10 +436,8 @@ func (m *serverKeyExchangeMsg) MakeLog(ka keyAgreement) *ServerKeyExchange { switch ka := ka.(type) { case *rsaKeyAgreement: skx.RSAParams = ka.RSAParams() - errAuth = ka.verifyError case *ecdheKeyAgreement: skx.ECDHParams = ka.ECDHParams() - errAuth = ka.verifyError default: break } @@ -494,13 +492,15 @@ func (m *clientHandshakeState) MakeLog() *KeyMaterial { } func (m *clientHandshakeStateTLS13) MakeLog() *KeyMaterial { - keymat := new(KeyMaterial) + // TODO: excrypto: revisit for correctness + ems := m.masterSecret.ExporterMasterSecret(m.transcript) + res := ems.Exporter("client finished", nil, 0) + keymat := new(KeyMaterial) keymat.MasterSecret = new(MasterSecret) - keymat.MasterSecret.Length = len(m.masterSecret) - keymat.MasterSecret.Value = make([]byte, len(m.masterSecret)) - copy(keymat.MasterSecret.Value, m.masterSecret) - + keymat.MasterSecret.Value = make([]byte, len(res)) + keymat.MasterSecret.Length = len(res) + copy(keymat.MasterSecret.Value, res) return keymat } diff --git a/crypto/tls/tls_ka.go b/crypto/tls/tls_ka.go index 9248bedaafa..a424a0efb10 100644 --- a/crypto/tls/tls_ka.go +++ b/crypto/tls/tls_ka.go @@ -77,10 +77,9 @@ func (ka *ecdheKeyAgreement) ECDHParams() *jsonKeys.ECDHKeys { out.TLSCurveID = jsonKeys.TLSCurveID(ka.curveID) if ka.key != nil { out.ServerPrivateKey = ka.key.Bytes() - } - if len(ka.pub) > 0 { - out.ServerPublicKey = make([]byte, len(ka.pub)) - copy(out.ServerPublicKey, ka.pub) + kb := ka.key.PublicKey().Bytes() + out.ServerPublicKey = make([]byte, len(kb)) + copy(out.ServerPublicKey, kb) } return out } @@ -90,10 +89,9 @@ func (ka *ecdheKeyAgreement) ClientECDHParams() *jsonKeys.ECDHKeys { out.TLSCurveID = jsonKeys.TLSCurveID(ka.curveID) if ka.key != nil { out.ClientPrivateKey = ka.key.Bytes() - } - if len(ka.pub) > 0 { - out.ClientPublicKey = make([]byte, len(ka.pub)) - copy(out.ClientPublicKey, ka.pub) + kb := ka.key.PublicKey().Bytes() + out.ServerPublicKey = make([]byte, len(kb)) + copy(out.ServerPublicKey, kb) } return out } diff --git a/crypto/tls/tls_test.go b/crypto/tls/tls_test.go index ade7f1bf106..d755251136f 100644 --- a/crypto/tls/tls_test.go +++ b/crypto/tls/tls_test.go @@ -7,7 +7,6 @@ package tls import ( "bytes" "context" - "crypto/rand" "encoding/json" "encoding/pem" "errors" @@ -23,14 +22,19 @@ import ( "testing" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" + "github.com/runZeroInc/excrypto/crypto/ecdh" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/internal/hpke" + "github.com/runZeroInc/excrypto/crypto/tls/internal/fips140tls" "github.com/runZeroInc/excrypto/crypto/x509" "github.com/runZeroInc/excrypto/crypto/x509/pkix" "github.com/runZeroInc/excrypto/encoding/asn1" - "github.com/runZeroInc/excrypto/internal/godebug" "github.com/runZeroInc/excrypto/internal/testenv" + "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" ) var rsaCertPEM = `-----BEGIN CERTIFICATE----- @@ -176,6 +180,40 @@ func newLocalListener(t testing.TB) net.Listener { return ln } +func runWithFIPSEnabled(t *testing.T, testFunc func(t *testing.T)) { + originalFIPS := fips140tls.Required() + defer func() { + if originalFIPS { + fips140tls.Force() + } else { + fips140tls.TestingOnlyAbandon() + } + }() + + fips140tls.Force() + t.Run("fips140tls", testFunc) +} + +func runWithFIPSDisabled(t *testing.T, testFunc func(t *testing.T)) { + originalFIPS := fips140tls.Required() + defer func() { + if originalFIPS { + fips140tls.Force() + } else { + fips140tls.TestingOnlyAbandon() + } + }() + + fips140tls.TestingOnlyAbandon() + t.Run("no-fips140tls", testFunc) +} + +func skipFIPS(t *testing.T) { + if fips140tls.Required() { + t.Skip("skipping test in FIPS mode") + } +} + func TestDialTimeout(t *testing.T) { if testing.Short() { t.Skip("skipping in short mode") @@ -774,7 +812,7 @@ func TestWarningAlertFlood(t *testing.T) { } func TestCloneFuncFields(t *testing.T) { - const expectedCount = 9 + const expectedCount = 10 called := 0 c1 := Config{ @@ -814,6 +852,10 @@ func TestCloneFuncFields(t *testing.T) { called |= 1 << 8 return nil }, + GetEncryptedClientHelloKeys: func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) { + called |= 1 << 9 + return nil, nil + }, } c2 := c1.Clone() @@ -827,6 +869,7 @@ func TestCloneFuncFields(t *testing.T) { c2.UnwrapSession(nil, ConnectionState{}) c2.WrapSession(ConnectionState{}, nil) c2.EncryptedClientHelloRejectionVerify(ConnectionState{}) + c2.GetEncryptedClientHelloKeys(nil) if called != (1<= 0 { - org = org[:i] - parentOrg = name[i+1:] - } - tmpl := &Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{org}, - }, - NotBefore: time.Unix(0, 0), - NotAfter: time.Unix(0, 0), - - KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature, - ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, - BasicConstraintsValid: true, - } - if mode&^boringCertFIPSOK == boringCertLeaf { - tmpl.DNSNames = []string{"example.com"} - } else { - tmpl.IsCA = true - tmpl.KeyUsage |= KeyUsageCertSign - } - - var pcert *Certificate - var pkey interface{} - if parent != nil { - pcert = parent.cert - pkey = parent.key - } else { - pcert = tmpl - pkey = key - } - - var pub interface{} - var desc string - switch k := key.(type) { - case *rsa.PrivateKey: - pub = &k.PublicKey - desc = fmt.Sprintf("RSA-%d", k.N.BitLen()) - case *ecdsa.PrivateKey: - pub = &k.PublicKey - desc = "ECDSA-" + k.Curve.Params().Name - default: - t.Fatalf("invalid key %T", key) - } - - der, err := CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) - if err != nil { - t.Fatal(err) - } - cert, err := ParseCertificate(der) - if err != nil { - t.Fatal(err) - } - - /* - // Tell isBoringCertificate to enforce FIPS restrictions for this check. - fipstls.Force() - defer fipstls.Abandon() - */ - - fipsOK := mode&boringCertFIPSOK != 0 - if boringAllowCert(cert) != fipsOK { - t.Errorf("boringAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK) - } - return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} -} diff --git a/crypto/x509/cert_pool.go b/crypto/x509/cert_pool.go index 897d8387c8a..7b077e5998f 100644 --- a/crypto/x509/cert_pool.go +++ b/crypto/x509/cert_pool.go @@ -293,53 +293,3 @@ func (s *CertPool) AddCertWithConstraint(cert *Certificate, constraint func([]*C return cert, nil }, constraint) } - -// Certificates returns all validate certificates in the pool. -func (s *CertPool) Certificates() []*Certificate { - res := make([]*Certificate, 0, s.len()) - for i := range s.len() { - c, certErr := s.lazyCerts[i].getCert() - if certErr != nil { - continue - } - res = append(res, c) - } - return res -} - -func (s *CertPool) Contains(cert *Certificate) bool { - return s.contains(cert) -} - -func (s *CertPool) Size() int { - return len(s.Certificates()) -} - -// Covers returns true if all certs in pool are in s. -func (s *CertPool) Covers(pool *CertPool) bool { - if pool == nil { - return true - } - for _, c := range pool.Certificates() { - if !s.Contains(c) { - return false - } - } - return true -} - -// Sum returns the union of two certificate pools as a new certificate pool. -func (s *CertPool) Sum(other *CertPool) (sum *CertPool) { - sum = NewCertPool() - if s != nil { - for _, c := range s.Certificates() { - sum.AddCert(c) - } - } - if other != nil { - for _, c := range other.Certificates() { - sum.AddCert(c) - } - } - return -} diff --git a/crypto/x509/cert_pool_test.go b/crypto/x509/cert_pool_test.go index 479e745e7fb..a12beda83d3 100644 --- a/crypto/x509/cert_pool_test.go +++ b/crypto/x509/cert_pool_test.go @@ -4,11 +4,7 @@ package x509 -import ( - "bytes" - "crypto/rand" - "testing" -) +import "testing" func TestCertPoolEqual(t *testing.T) { tc := &Certificate{Raw: []byte{1, 2, 3}, RawSubject: []byte{2}} @@ -110,178 +106,3 @@ func TestCertPoolEqual(t *testing.T) { }) } } - -func TestSubjects(t *testing.T) { - certs := makeRandomCertsForPool(1000) - pool := NewCertPool() - for _, c := range certs { - pool.AddCert(c) - } - subjects := pool.Subjects() - for i := range subjects { - if !bytes.Equal(subjects[i], pool.Certificates()[i].RawSubject) { - t.Fail() - } - } -} - -func TestSumAndContains(t *testing.T) { - certs1 := makeRandomCertsForPool(1000) - pool1 := NewCertPool() - for _, c := range certs1 { - pool1.AddCert(c) - } - certs2 := makeRandomCertsForPool(1000) - pool2 := NewCertPool() - for _, c := range certs2 { - pool2.AddCert(c) - } - sum := pool1.Sum(pool2) - for _, c := range pool1.Certificates() { - if !sum.Contains(c) { - t.Fail() - } - } - for _, c := range sum.Certificates() { - if !pool1.Contains(c) && !pool2.Contains(c) { - t.Fail() - } - } -} - -func TestSumAndSize(t *testing.T) { - certs1 := makeRandomCertsForPool(1000) - pool1 := NewCertPool() - for _, c := range certs1 { - pool1.AddCert(c) - } - certs2 := makeRandomCertsForPool(1000) - pool2 := NewCertPool() - for _, c := range certs2 { - pool2.AddCert(c) - } - sum := pool1.Sum(pool2) - if sum.Size() != 2000 { - t.Fail() - } -} - -func TestSumAndCovers(t *testing.T) { - certs1 := makeRandomCertsForPool(1000) - pool1 := NewCertPool() - for _, c := range certs1 { - pool1.AddCert(c) - } - certs2 := makeRandomCertsForPool(1000) - pool2 := NewCertPool() - for _, c := range certs2 { - pool2.AddCert(c) - } - sum := pool1.Sum(pool2) - if !sum.Covers(pool1) || !sum.Covers(pool2) { - t.Fail() - } - if pool1.Covers(sum) || pool2.Covers(sum) { - t.Fail() - } -} - -func makeRandomCertsForPool(n int) []*Certificate { - out := make([]*Certificate, 0, n) - for i := 0; i < n; i++ { - c := new(Certificate) - c.FingerprintSHA256 = make([]byte, 256/8) - if _, err := rand.Read(c.FingerprintSHA256); err != nil { - panic(err) - } - c.RawSubject = make([]byte, 1) - if _, err := rand.Read(c.RawSubject); err != nil { - panic(err) - } - c.SubjectKeyId = make([]byte, 2) - if _, err := rand.Read(c.SubjectKeyId); err != nil { - panic(err) - } - c.Raw = make([]byte, 2048) - if _, err := rand.Read(c.Raw); err != nil { - panic(err) - } - out = append(out, c) - } - return out -} - -func doBench(b *testing.B, certs []*Certificate) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool := NewCertPool() - for _, c := range certs { - pool.AddCert(c) - } - } -} - -func BenchmarkCertPoolAdd10(b *testing.B) { - certs := makeRandomCertsForPool(10) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd100(b *testing.B) { - certs := makeRandomCertsForPool(100) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd200(b *testing.B) { - certs := makeRandomCertsForPool(200) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd300(b *testing.B) { - certs := makeRandomCertsForPool(300) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd400(b *testing.B) { - certs := makeRandomCertsForPool(400) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd500(b *testing.B) { - certs := makeRandomCertsForPool(500) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd600(b *testing.B) { - certs := makeRandomCertsForPool(600) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd700(b *testing.B) { - certs := makeRandomCertsForPool(700) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd800(b *testing.B) { - certs := makeRandomCertsForPool(800) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd900(b *testing.B) { - certs := makeRandomCertsForPool(900) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd1000(b *testing.B) { - certs := makeRandomCertsForPool(1000) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd10000(b *testing.B) { - certs := makeRandomCertsForPool(10000) - doBench(b, certs) -} - -func BenchmarkCertPoolAdd100000(b *testing.B) { - certs := makeRandomCertsForPool(100000) - doBench(b, certs) -} diff --git a/crypto/x509/extended_key_usage.go b/crypto/x509/extended_key_usage.go index 774d64dc1ad..14d74cd6106 100644 --- a/crypto/x509/extended_key_usage.go +++ b/crypto/x509/extended_key_usage.go @@ -418,7 +418,6 @@ func (aux *auxExtendedKeyUsage) populateFromASN1(oid asn1.ObjectIdentifier) { aux.Any = true default: } - return } func (aux *auxExtendedKeyUsage) populateFromExtKeyUsage(eku ExtKeyUsage) { diff --git a/crypto/x509/extensions_test.go b/crypto/x509/extensions_test.go index 19d59a6944a..85816931627 100644 --- a/crypto/x509/extensions_test.go +++ b/crypto/x509/extensions_test.go @@ -512,7 +512,7 @@ func TestTorServiceDescriptorHashJSON(t *testing.T) { } expectedJSON := fmt.Sprintf( - `[{"onion":"https://zmap.onion","algorithm_name":"SHA256","hash":%q,"hash_bits":256}]`, + `[{"onion":"https://zmap.onion","algorithm_name":"SHA256","github.com/runZeroInc/excrypto/hash":%q,"hash_bits":256}]`, testHash.Hex()) out, err := json.Marshal(descs) diff --git a/crypto/x509/hybrid_pool_test.go b/crypto/x509/hybrid_pool_test.go index d104963ccfa..09f88d7e1f1 100644 --- a/crypto/x509/hybrid_pool_test.go +++ b/crypto/x509/hybrid_pool_test.go @@ -5,20 +5,20 @@ package x509_test import ( + "math/big" + "runtime" "testing" + "time" + "github.com/runZeroInc/excrypto/crypto/ecdsa" + "github.com/runZeroInc/excrypto/crypto/elliptic" + "github.com/runZeroInc/excrypto/crypto/rand" "github.com/runZeroInc/excrypto/crypto/tls" + "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/crypto/x509/pkix" + "github.com/runZeroInc/excrypto/internal/testenv" ) -func TestBasicTLS(t *testing.T) { - c, err := tls.Dial("tcp", "google.com:443", &tls.Config{}) - if err != nil { - t.Fatalf("tls connection failed: %s", err) - } - c.Close() -} - -/* func TestHybridPool(t *testing.T) { t.Parallel() if !(runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios") { @@ -88,24 +88,18 @@ func TestHybridPool(t *testing.T) { if err != nil { t.Fatalf("SystemCertPool failed: %s", err) } - - subCnt := len(pool.Subjects()) - if subCnt < 150 { - t.Errorf("SystemCertPool has %d subjects, wanted >= 150", subCnt) - } - opts := x509.VerifyOptions{Roots: pool} - _, err = googChain[0].Verify(opts) + _, _, _, err = googChain[0].Verify(opts) if err != nil { - t.Errorf("verification failed for google.com chain (system only pool): %s", err) + t.Fatalf("verification failed for google.com chain (system only pool): %s", err) } pool.AddCert(root) - _, err = googChain[0].Verify(opts) + _, _, _, err = googChain[0].Verify(opts) if err != nil { - t.Errorf("verification failed for google.com chain (hybrid pool): %s", err) + t.Fatalf("verification failed for google.com chain (hybrid pool): %s", err) } certTmpl := &x509.Certificate{ @@ -123,9 +117,8 @@ func TestHybridPool(t *testing.T) { t.Fatalf("failed to parse test cert: %s", err) } - _, err = cert.Verify(opts) + _, _, _, err = cert.Verify(opts) if err != nil { - t.Errorf("verification failed for custom chain (hybrid pool): %s", err) + t.Fatalf("verification failed for custom chain (hybrid pool): %s", err) } } -*/ diff --git a/crypto/x509/name_constraints_test.go b/crypto/x509/name_constraints_test.go index 2b542b0ea6b..a89630150ea 100644 --- a/crypto/x509/name_constraints_test.go +++ b/crypto/x509/name_constraints_test.go @@ -6,7 +6,6 @@ package x509 import ( "bytes" - "crypto/rand" "encoding/hex" "encoding/pem" "fmt" @@ -20,6 +19,8 @@ import ( "testing" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/crypto/x509/pkix" @@ -147,8 +148,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"dns:example.com"}, }, - // zcrypto - // expectedError: "\"example.com\" is not permitted", + expectedError: "\"example.com\" is not permitted", }, // #6: .example.com matches subdomains. @@ -1004,8 +1004,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://1.2.3.4/"}, }, - // zcrypto - // expectedError: "URI with IP", + expectedError: "URI with IP", }, // #52: URIs with IPs and ports are rejected @@ -1023,8 +1022,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://1.2.3.4:43/"}, }, - // zcrypto - // expectedError: "URI with IP", + expectedError: "URI with IP", }, // #53: URIs with IPv6 addresses are also rejected @@ -1042,8 +1040,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://[2006:abcd::1]/"}, }, - // zcrypto - // expectedError: "URI with IP", + expectedError: "URI with IP", }, // #54: URIs with IPv6 addresses with ports are also rejected @@ -1061,8 +1058,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://[2006:abcd::1]:16/"}, }, - // zcrypto - // expectedError: "URI with IP", + expectedError: "URI with IP", }, // #55: URI constraints are effective @@ -1080,8 +1076,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://bar.com/"}, }, - // zcrypto - // expectedError: "\"http://bar.com/\" is not permitted", + expectedError: "\"http://bar.com/\" is not permitted", }, // #56: URI constraints are effective @@ -1099,8 +1094,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:http://foo.com/"}, }, - // zcrypto - // expectedError: "\"http://foo.com/\" is excluded", + expectedError: "\"http://foo.com/\" is excluded", }, // #57: URI constraints can allow subdomains @@ -1153,8 +1147,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:urn:example"}, }, - // zcrypto - // expectedError: "URI with empty host", + expectedError: "URI with empty host", }, // #60: excluding all IPv6 addresses doesn't exclude all IPv4 addresses @@ -1427,8 +1420,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"uri:https://example.com/test"}, }, - // zcrypto - // expectedError: "\"https://example.com/test\" is excluded", + expectedError: "\"https://example.com/test\" is excluded", }, // #75: serverAuth in a leaf shouldn't permit clientAuth when requested in @@ -1499,8 +1491,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"dns:this is invalid"}, }, - // zcrypto - // expectedError: "cannot parse dnsName", + expectedError: "cannot parse dnsName", }, // #79: an invalid email SAN will be detected if any name constraint @@ -1519,8 +1510,7 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{ sans: []string{"email:this @ is invalid"}, }, - // zcrypto - // expectedError: "cannot parse rfc822Name", + expectedError: "cannot parse rfc822Name", }, // #80: if several EKUs are requested, satisfying any of them is sufficient. @@ -1618,6 +1608,23 @@ var nameConstraintsTests = []nameConstraintsTest{ leaf: leafSpec{sans: []string{"dns:.example.com"}}, expectedError: "cannot parse dnsName \".example.com\"", }, + // #86: URIs with IPv6 addresses with zones and ports are rejected + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://[2006:abcd::1%25.example.com]:16/"}, + }, + expectedError: "URI with IP", + }, } func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { @@ -1769,7 +1776,7 @@ func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) } func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error { - parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, URIs []string, err error) { + parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) { for _, constraint := range constraints { switch { case strings.HasPrefix(constraint, "dns:"): @@ -1786,14 +1793,14 @@ func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate emailAddrs = append(emailAddrs, constraint[6:]) case strings.HasPrefix(constraint, "uri:"): - URIs = append(URIs, constraint[4:]) + uriDomains = append(uriDomains, constraint[4:]) default: return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint) } } - return dnsNames, ips, emailAddrs, URIs, err + return dnsNames, ips, emailAddrs, uriDomains, err } handleSpecialConstraint := func(constraint string, isExcluded bool) bool { @@ -1962,7 +1969,8 @@ func TestConstraintCases(t *testing.T) { CurrentTime: time.Unix(1500, 0), KeyUsages: test.requestedEKUs, } - _, _, _, err = leafCert.Verify(verifyOpts) + + chainValid, chainExpired, chainNever, err := leafCert.Verify(verifyOpts) logInfo := true if len(test.expectedError) == 0 { @@ -1972,8 +1980,8 @@ func TestConstraintCases(t *testing.T) { logInfo = false } } else { - if err == nil { - t.Error("unexpected success") + if err == nil && len(chainExpired) == 0 && len(chainNever) == 0 { + t.Errorf("unexpected success with valid certs: %v", chainValid) } else if !strings.Contains(err.Error(), test.expectedError) { t.Errorf("expected error containing %q, but got: %s", test.expectedError, err) } else { @@ -1984,7 +1992,7 @@ func TestConstraintCases(t *testing.T) { if logInfo { certAsPEM := func(cert *Certificate) string { var buf bytes.Buffer - pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) + _ = pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) return buf.String() } t.Errorf("root:\n%s", certAsPEM(rootPool.mustCert(t, 0))) @@ -2109,7 +2117,7 @@ func TestRFC2821Parsing(t *testing.T) { } } -// zcrypto: allow invalid name constraints +// excrypto: allow invalid name constraints /* func TestBadNamesInConstraints(t *testing.T) { constraintParseError := func(err error) bool { diff --git a/crypto/x509/notboring.go b/crypto/x509/notboring.go deleted file mode 100644 index c0989958eb4..00000000000 --- a/crypto/x509/notboring.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !boringcryptoForced - -package x509 - -func boringAllowCert(_ *Certificate) bool { return true } diff --git a/crypto/x509/oid_test.go b/crypto/x509/oid_test.go index a1d823eb1e9..2ffa6af0c5a 100644 --- a/crypto/x509/oid_test.go +++ b/crypto/x509/oid_test.go @@ -134,12 +134,12 @@ func TestOIDEqual(t *testing.T) { oid2 OID eq bool }{ - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3}), eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 4}), eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3, 4}), eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{2, 33, 22}), oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 3}), eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 4}), eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 3, 4}), eq: false}, + {oid: mustNewOIDFromInts([]uint64{2, 33, 22}), oid2: mustNewOIDFromInts([]uint64{2, 33, 23}), eq: false}, {oid: OID{}, oid2: OID{}, eq: true}, - {oid: OID{}, oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false}, + {oid: OID{}, oid2: mustNewOIDFromInts([]uint64{2, 33, 23}), eq: false}, } for _, tt := range cases { @@ -278,32 +278,32 @@ func TestOIDEqualASN1OID(t *testing.T) { oid2 asn1.ObjectIdentifier eq bool }{ - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 4}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3, 4}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 22}), oid2: asn1.ObjectIdentifier{1, 33, 23}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 23}), oid2: asn1.ObjectIdentifier{1, 33, 22}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 127}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 255}), oid2: asn1.ObjectIdentifier{1, 33, 255}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: true}, - {oid: mustNewOIDFromInts(t, []uint64{2, 33, 257}), oid2: asn1.ObjectIdentifier{2, 33, 256}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{2, 33, 256}), oid2: asn1.ObjectIdentifier{2, 33, 257}, eq: false}, - - {oid: mustNewOIDFromInts(t, []uint64{1, 33}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33}, eq: false}, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 4}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3, 4}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 22}), oid2: asn1.ObjectIdentifier{1, 33, 23}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 23}), oid2: asn1.ObjectIdentifier{1, 33, 22}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 127}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 255}), oid2: asn1.ObjectIdentifier{1, 33, 255}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: true}, + {oid: mustNewOIDFromInts([]uint64{2, 33, 257}), oid2: asn1.ObjectIdentifier{2, 33, 256}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{2, 33, 256}), oid2: asn1.ObjectIdentifier{2, 33, 257}, eq: false}, + + {oid: mustNewOIDFromInts([]uint64{1, 33}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: true}, { - oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32 + 1}), + oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32 + 1}), oid2: asn1.ObjectIdentifier{1, 33 /*convert to int, so that it compiles on 32bit*/, int(maxInt32PlusOne)}, eq: false, }, - {oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{}, eq: false}, + {oid: mustNewOIDFromInts([]uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{}, eq: false}, {oid: OID{}, oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: false}, {oid: OID{}, oid2: asn1.ObjectIdentifier{}, eq: false}, } @@ -332,7 +332,7 @@ func TestOIDUnmarshalBinary(t *testing.T) { } func BenchmarkOIDMarshalUnmarshalText(b *testing.B) { - oid := mustNewOIDFromInts(b, []uint64{1, 2, 3, 9999, 1024}) + oid := mustNewOIDFromInts([]uint64{1, 2, 3, 9999, 1024}) for range b.N { text, err := oid.MarshalText() if err != nil { @@ -344,12 +344,3 @@ func BenchmarkOIDMarshalUnmarshalText(b *testing.B) { } } } - -func mustNewOIDFromInts(t testing.TB, ints []uint64) OID { - t.Helper() - oid, err := OIDFromInts(ints) - if err != nil { - t.Fatalf("OIDFromInts(%v) unexpected error: %v", ints, err) - } - return oid -} diff --git a/crypto/x509/parser.go b/crypto/x509/parser.go index 8e2cbfa2940..fc640df2c0e 100644 --- a/crypto/x509/parser.go +++ b/crypto/x509/parser.go @@ -8,6 +8,7 @@ import ( "bytes" "errors" "fmt" + "math" "math/big" "net" "strconv" @@ -61,8 +62,25 @@ func isPrintable(b byte) bool { func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { switch tag { case cryptobyte_asn1.T61String: - return string(value), nil + // T.61 is a defunct ITU 8-bit character encoding which preceded Unicode. + // T.61 uses a code page layout that _almost_ exactly maps to the code + // page layout of the ISO 8859-1 (Latin-1) character encoding, with the + // exception that a number of characters in Latin-1 are not present + // in T.61. + // + // Instead of mapping which characters are present in Latin-1 but not T.61, + // we just treat these strings as being encoded using Latin-1. This matches + // what most of the world does, including BoringSSL. + buf := make([]byte, 0, len(value)) + for _, v := range value { + // All the 1-byte UTF-8 runes map 1-1 with Latin-1. + buf = utf8.AppendRune(buf, rune(v)) + } + return string(buf), nil case cryptobyte_asn1.PrintableString: + if asn1.AllowPermissiveParsing { + return string(value), nil + } for _, b := range value { if !isPrintable(b) { return "", errors.New("invalid PrintableString") @@ -70,11 +88,22 @@ func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { } return string(value), nil case cryptobyte_asn1.UTF8String: + if asn1.AllowPermissiveParsing { + return string(value), nil + } if !utf8.Valid(value) { return "", errors.New("invalid UTF-8 string") } return string(value), nil case cryptobyte_asn1.Tag(asn1.TagBMPString): + // BMPString uses the defunct UCS-2 16-bit character encoding, which + // covers the Basic Multilingual Plane (BMP). UTF-16 was an extension of + // UCS-2, containing all of the same code points, but also including + // multi-code point characters (by using surrogate code points). We can + // treat a UCS-2 encoded string as a UTF-16 encoded string, as long as + // we reject out the UTF-16 specific code points. This matches the + // BoringSSL behavior. + if len(value)%2 != 0 { return "", errors.New("invalid BMPString") } @@ -86,18 +115,38 @@ func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { s := make([]uint16, 0, len(value)/2) for len(value) > 0 { - s = append(s, uint16(value[0])<<8+uint16(value[1])) + if asn1.AllowPermissiveParsing { + s = append(s, uint16(value[0])<<8+uint16(value[1])) + value = value[2:] + continue + } + point := uint16(value[0])<<8 + uint16(value[1]) + // Reject UTF-16 code points that are permanently reserved + // noncharacters (0xfffe, 0xffff, and 0xfdd0-0xfdef) and surrogates + // (0xd800-0xdfff). + if point == 0xfffe || point == 0xffff || + (point >= 0xfdd0 && point <= 0xfdef) || + (point >= 0xd800 && point <= 0xdfff) { + return "", errors.New("invalid BMPString") + } + s = append(s, point) value = value[2:] } return string(utf16.Decode(s)), nil case cryptobyte_asn1.IA5String: s := string(value) + if asn1.AllowPermissiveParsing { + return string(value), nil + } if isIA5String(s) != nil { return "", errors.New("invalid IA5String") } return s, nil case cryptobyte_asn1.Tag(asn1.TagNumericString): + if asn1.AllowPermissiveParsing { + return string(value), nil + } for _, b := range value { if !('0' <= b && b <= '9' || b == ' ') { return "", errors.New("invalid NumericString") @@ -222,7 +271,7 @@ func parsePublicKey(keyData *publicKeyInfo) (any, error) { der := cryptobyte.String(keyData.PublicKey.RightAlign()) switch { case oid.Equal(oidPublicKeyRSA): - // zcrypto + // excrypto: support RSA public keys with NULL parameters /* // RSA public keys must have a NULL in the parameters. // See RFC 3279, Section 2.3.1. @@ -241,8 +290,7 @@ func parsePublicKey(keyData *publicKeyInfo) (any, error) { if !der.ReadASN1Integer(&p.E) { return nil, errors.New("x509: invalid RSA public exponent") } - - // zcrypto + // excrypto if !asn1.AllowPermissiveParsing { if p.N.Sign() <= 0 { return nil, errors.New("x509: RSA modulus is not a positive number") @@ -349,14 +397,16 @@ func parseBasicConstraintsExtension(der cryptobyte.String) (bool, int, error) { return false, 0, errors.New("x509: invalid basic constraints") } } + maxPathLen := -1 if der.PeekASN1Tag(cryptobyte_asn1.INTEGER) { - if !der.ReadASN1Integer(&maxPathLen) { + var mpl uint + if !der.ReadASN1Integer(&mpl) || mpl > math.MaxInt { return false, 0, errors.New("x509: invalid basic constraints") } + maxPathLen = int(mpl) } - // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) return isCA, maxPathLen, nil } @@ -394,7 +444,8 @@ func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string } dnsNames = append(dnsNames, string(name)) case nameTypeURI: - uris = append(uris, string(data)) + uriStr := string(data) + uris = append(uris, uriStr) case nameTypeIP: switch len(data) { case net.IPv4len, net.IPv6len: @@ -450,85 +501,60 @@ func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.Obj return extKeyUsages, unknownUsages, nil } -func parseCertificatePoliciesExtension(out *Certificate, der cryptobyte.String) error { - var err error - // RFC 5280 4.2.1.4: Certificate Policies - var policies []policyInformation - if _, err = asn1.Unmarshal(der, &policies); err != nil { - return err - } - - out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) - out.QualifierId = make([][]asn1.ObjectIdentifier, len(policies)) - out.ExplicitTexts = make([][]asn1.RawValue, len(policies)) - out.NoticeRefOrgnization = make([][]asn1.RawValue, len(policies)) - out.NoticeRefNumbers = make([][]NoticeNumber, len(policies)) - out.ParsedExplicitTexts = make([][]string, len(policies)) - out.ParsedNoticeRefOrganization = make([][]string, len(policies)) - out.CPSuri = make([][]string, len(policies)) - out.UserNotices = make([][]UserNotice, len(policies)) - - for i, policy := range policies { - - // TODO: Avoid double marshal by adding a conversion function - if oidVal, err := ParseOID(policy.Policy.String()); err == nil { - out.Policies = append(out.Policies, oidVal) - } - - out.PolicyIdentifiers[i] = policy.Policy - // parse optional Qualifier for zlint - for _, qualifier := range policy.Qualifiers { - out.QualifierId[i] = append(out.QualifierId[i], qualifier.PolicyQualifierId) - userNoticeOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} - cpsURIOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} - - if qualifier.PolicyQualifierId.Equal(userNoticeOID) { - var un userNotice - _, err := asn1.Unmarshal(qualifier.Qualifier.FullBytes, &un) - if err != nil && !asn1.AllowPermissiveParsing { - return err - } - if err == nil { - groupUserNotice := UserNotice{} - if len(un.ExplicitText.Bytes) != 0 { - out.ExplicitTexts[i] = append(out.ExplicitTexts[i], un.ExplicitText) - parsed := string(un.ExplicitText.Bytes) - out.ParsedExplicitTexts[i] = append(out.ParsedExplicitTexts[i], parsed) - - groupUserNotice.ExplicitText = &parsed - } - - if un.NoticeRef.Organization.Bytes != nil || un.NoticeRef.NoticeNumbers != nil { - out.NoticeRefOrgnization[i] = append(out.NoticeRefOrgnization[i], un.NoticeRef.Organization) - out.NoticeRefNumbers[i] = append(out.NoticeRefNumbers[i], un.NoticeRef.NoticeNumbers) - out.ParsedNoticeRefOrganization[i] = append(out.ParsedNoticeRefOrganization[i], string(un.NoticeRef.Organization.Bytes)) - - groupUserNotice.NoticeReference = &NoticeReference{ - Organization: string(un.NoticeRef.Organization.Bytes), - NoticeNumbers: un.NoticeRef.NoticeNumbers, - } - } +func parseCertificatePoliciesExtension(out *Certificate, der cryptobyte.String) ([]OID, error) { + var oids []OID + var oidsRaw []asn1.ObjectIdentifier - out.UserNotices[i] = append(out.UserNotices[i], groupUserNotice) - } + seenOIDs := map[string]bool{} + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + err := errors.New("x509: invalid certificate policies") + if !asn1.AllowPermissiveParsing { + return nil, err + } else { + out.PermissiveErrors = append(out.PermissiveErrors, err) + return nil, nil + } + } + for !der.Empty() { + var cp cryptobyte.String + var OIDBytes cryptobyte.String + if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) || !cp.ReadASN1(&OIDBytes, cryptobyte_asn1.OBJECT_IDENTIFIER) { + err := errors.New("x509: invalid certificate policies: malformed OID") + if !asn1.AllowPermissiveParsing { + return nil, err } - if qualifier.PolicyQualifierId.Equal(cpsURIOID) { - var cpsURIRaw asn1.RawValue - _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &cpsURIRaw) - if err != nil && !asn1.AllowPermissiveParsing { - return err - } - if err == nil { - out.CPSuri[i] = append(out.CPSuri[i], string(cpsURIRaw.Bytes)) - } + out.PermissiveErrors = append(out.PermissiveErrors, err) + continue + } + if seenOIDs[string(OIDBytes)] { + err := errors.New("x509: invalid certificate policies: duplicate OID") + if !asn1.AllowPermissiveParsing { + return nil, err } + out.PermissiveErrors = append(out.PermissiveErrors, err) } + seenOIDs[string(OIDBytes)] = true + oid, ok := newOIDFromDER(OIDBytes) + if !ok { + err := errors.New("x509: invalid certificate policies") + if !asn1.AllowPermissiveParsing { + return nil, err + } else { + out.PermissiveErrors = append(out.PermissiveErrors, err) + continue + } + } + if oidRaw, ok := oid.toASN1OID(); ok { + oidsRaw = append(oidsRaw, oidRaw) + } + oids = append(oids, oid) } + if out.SelfSigned { out.ValidationLevel = UnknownValidationLevel } else { // See http://unmitigatedrisk.com/?p=203 - validationLevel := getMaxCertValidationLevel(out.PolicyIdentifiers) + validationLevel := getMaxCertValidationLevel(oidsRaw) if validationLevel == UnknownValidationLevel { if (len(out.Subject.Organization) > 0 && out.Subject.Organization[0] == out.Subject.CommonName) || (len(out.Subject.OrganizationalUnit) > 0 && strings.Contains(out.Subject.OrganizationalUnit[0], "Domain Control Validated")) { if len(out.Subject.Locality) == 0 && len(out.Subject.Province) == 0 && len(out.Subject.PostalCode) == 0 { @@ -541,7 +567,75 @@ func parseCertificatePoliciesExtension(out *Certificate, der cryptobyte.String) out.ValidationLevel = validationLevel } - return nil + /* + TODO: Rework policy parsing to use cryptobytes vs asn1.Unmarshal due to big-int 128 base issues + var err error + var policies []policyInformation + if _, err = asn1.Unmarshal(rawCopy, &policies); err != nil { + return nil, err + } + + out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) + out.QualifierId = make([][]asn1.ObjectIdentifier, len(policies)) + out.ExplicitTexts = make([][]asn1.RawValue, len(policies)) + out.NoticeRefOrgnization = make([][]asn1.RawValue, len(policies)) + out.NoticeRefNumbers = make([][]NoticeNumber, len(policies)) + out.ParsedExplicitTexts = make([][]string, len(policies)) + out.ParsedNoticeRefOrganization = make([][]string, len(policies)) + out.CPSuri = make([][]string, len(policies)) + out.UserNotices = make([][]UserNotice, len(policies)) + + for i, policy := range policies { + for _, qualifier := range policy.Qualifiers { + out.QualifierId[i] = append(out.QualifierId[i], qualifier.PolicyQualifierId) + userNoticeOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} + cpsURIOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} + + if qualifier.PolicyQualifierId.Equal(userNoticeOID) { + var un userNotice + _, err := asn1.Unmarshal(qualifier.Qualifier.FullBytes, &un) + if err != nil && !asn1.AllowPermissiveParsing { + return nil, err + } + if err == nil { + groupUserNotice := UserNotice{} + if len(un.ExplicitText.Bytes) != 0 { + out.ExplicitTexts[i] = append(out.ExplicitTexts[i], un.ExplicitText) + parsed := string(un.ExplicitText.Bytes) + out.ParsedExplicitTexts[i] = append(out.ParsedExplicitTexts[i], parsed) + + groupUserNotice.ExplicitText = &parsed + } + + if un.NoticeRef.Organization.Bytes != nil || un.NoticeRef.NoticeNumbers != nil { + out.NoticeRefOrgnization[i] = append(out.NoticeRefOrgnization[i], un.NoticeRef.Organization) + out.NoticeRefNumbers[i] = append(out.NoticeRefNumbers[i], un.NoticeRef.NoticeNumbers) + out.ParsedNoticeRefOrganization[i] = append(out.ParsedNoticeRefOrganization[i], string(un.NoticeRef.Organization.Bytes)) + + groupUserNotice.NoticeReference = &NoticeReference{ + Organization: string(un.NoticeRef.Organization.Bytes), + NoticeNumbers: un.NoticeRef.NoticeNumbers, + } + } + + out.UserNotices[i] = append(out.UserNotices[i], groupUserNotice) + } + } + if qualifier.PolicyQualifierId.Equal(cpsURIOID) { + var cpsURIRaw asn1.RawValue + _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &cpsURIRaw) + if err != nil && !asn1.AllowPermissiveParsing { + return nil, err + } + if err == nil { + out.CPSuri[i] = append(out.CPSuri[i], string(cpsURIRaw.Bytes)) + } + } + } + } + */ + + return oids, nil } // isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits. @@ -604,22 +698,13 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle return false, errors.New("x509: empty name constraints extension") } - getValues := func(subtrees cryptobyte.String) ( - dnsNames []string, - ips []*net.IPNet, emails, - uriDomains []string, - x400Addrs []string, - dirNames []pkix.Name, - partyNames []pkix.EDIPartyName, - permitOids []asn1.ObjectIdentifier, - err error, - ) { + getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, x400Addrs []string, dirNames []pkix.Name, partyNames []pkix.EDIPartyName, permitOids []asn1.ObjectIdentifier, err error) { + for !subtrees.Empty() { var seq, value cryptobyte.String var tag cryptobyte_asn1.Tag if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) || !seq.ReadAnyASN1(&value, &tag) { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension") } @@ -629,7 +714,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle ipTag = cryptobyte_asn1.Tag(7).ContextSpecific() uriTag = cryptobyte_asn1.Tag(6).ContextSpecific() x400Tag = cryptobyte_asn1.Tag(3).ContextSpecific() - dirNameTag = cryptobyte_asn1.Tag(4).ContextSpecific() + dirNameTag = cryptobyte_asn1.Tag(4).ContextSpecific().Constructed() partyNameTag = cryptobyte_asn1.Tag(5).ContextSpecific() permitOidTag = cryptobyte_asn1.Tag(8).ContextSpecific() ) @@ -637,10 +722,10 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle switch tag { case dnsTag: domain := string(value) - if err = isIA5String(domain); err != nil { - // TODO: zcrypto allow skipping over invalid names - err = fmt.Errorf("x509: invalid constraint value: %v", err) - return + if err := isIA5String(domain); err != nil { + if !asn1.AllowPermissiveParsing { + return nil, nil, nil, nil, nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } } trimmedDomain := domain @@ -652,10 +737,10 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle trimmedDomain = trimmedDomain[1:] } if _, ok := domainToReverseLabels(trimmedDomain); !ok { - err = fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) - return + // TODO: Support permissive values + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) } - dnsNames = append(dnsNames, trimmedDomain) + dnsNames = append(dnsNames, domain) case ipTag: l := len(value) @@ -671,11 +756,12 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle mask = value[16:] default: - err = fmt.Errorf("x509: IP constraint contained value of length %d", l) - return + // TODO: Support permissive values + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l) } if !isValidIPMask(mask) { + // TODO: Support permissive values return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask) } @@ -683,17 +769,16 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle case emailTag: constraint := string(value) - if err = isIA5String(constraint); err != nil { - err = fmt.Errorf("x509: invalid constraint value: %v", err) - return + if err := isIA5String(constraint); err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) } // If the constraint contains an @ then // it specifies an exact mailbox name. if strings.Contains(constraint, "@") { if _, ok := parseRFC2821Mailbox(constraint); !ok { - err = fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) - return + // TODO: Support permissive values + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) } } else { // Otherwise it's a domain name. @@ -702,22 +787,20 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle domain = domain[1:] } if _, ok := domainToReverseLabels(domain); !ok { - err = fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) - return + // TODO: Support permissive values + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) } } emails = append(emails, constraint) case uriTag: domain := string(value) - if err = isIA5String(domain); err != nil { - err = fmt.Errorf("x509: invalid constraint value: %v", err) - return + if err := isIA5String(domain); err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) } if net.ParseIP(domain) != nil { - err = fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) - return + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) } trimmedDomain := domain @@ -729,8 +812,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle trimmedDomain = trimmedDomain[1:] } if _, ok := domainToReverseLabels(trimmedDomain); !ok { - err = fmt.Errorf("x509: failed to parse URI constraint %q", domain) - return + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) } uriDomains = append(uriDomains, domain) @@ -784,8 +866,8 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle } if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, - out.PermittedURIDomains, out.PermittedX400Addresses, out.DirectoryNames, - out.EDIPartyNames, out.PermittedRegisteredIDs, err = getValues(permitted); err != nil { + out.PermittedURIDomains, out.PermittedX400Addresses, out.PermittedDirectoryNames, + out.PermittedEdiPartyNames, out.PermittedRegisteredIDs, err = getValues(permitted); err != nil { return false, err } if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, @@ -804,8 +886,8 @@ func processExtensions(out *Certificate) error { oidStr := e.Id.String() unhandled := false - // zcrypto - // TODO: Handle additional permissive parsing (skip most returns on error) + // excrypto + // TODO: Handle additional permissive parsing (avoid returning early on error) if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { @@ -918,7 +1000,6 @@ func processExtensions(out *Certificate) error { out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(uri)) } } - case 35: out.AuthorityKeyId, err = parseAuthorityKeyIdentifier(e) if err != nil { @@ -928,6 +1009,36 @@ func processExtensions(out *Certificate) error { out.PermissiveErrors = append(out.PermissiveErrors, fmt.Errorf("extension %d/%s: %w", extIdx, oidStr, err)) } } + case 36: + // excrypto: TODO: enable permissive parsing + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid policy constraints extension") + } + if val.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) { + var v int64 + if !val.ReadASN1Int64WithTag(&v, cryptobyte_asn1.Tag(0).ContextSpecific()) { + return errors.New("x509: invalid policy constraints extension") + } + out.RequireExplicitPolicy = int(v) + // Check for overflow. + if int64(out.RequireExplicitPolicy) != v { + return errors.New("x509: policy constraints requireExplicitPolicy field overflows int") + } + out.RequireExplicitPolicyZero = out.RequireExplicitPolicy == 0 + } + if val.PeekASN1Tag(cryptobyte_asn1.Tag(1).ContextSpecific()) { + var v int64 + if !val.ReadASN1Int64WithTag(&v, cryptobyte_asn1.Tag(1).ContextSpecific()) { + return errors.New("x509: invalid policy constraints extension") + } + out.InhibitPolicyMapping = int(v) + // Check for overflow. + if int64(out.InhibitPolicyMapping) != v { + return errors.New("x509: policy constraints inhibitPolicyMapping field overflows int") + } + out.InhibitPolicyMappingZero = out.InhibitPolicyMapping == 0 + } case 37: out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) if err != nil { @@ -937,8 +1048,7 @@ func processExtensions(out *Certificate) error { out.PermissiveErrors = append(out.PermissiveErrors, fmt.Errorf("extension %d/%s: %w", extIdx, oidStr, err)) } } - case 14: - // RFC 5280, 4.2.1.2 + case 14: // RFC 5280, 4.2.1.2 if e.Critical { // Conforming CAs MUST mark this extension as non-critical return errors.New("x509: subject key identifier incorrectly marked critical") @@ -950,7 +1060,7 @@ func processExtensions(out *Certificate) error { } out.SubjectKeyId = skid case 32: - err = parseCertificatePoliciesExtension(out, e.Value) + out.Policies, err = parseCertificatePoliciesExtension(out, e.Value) if err != nil { if !asn1.AllowPermissiveParsing { return err @@ -958,6 +1068,33 @@ func processExtensions(out *Certificate) error { out.PermissiveErrors = append(out.PermissiveErrors, fmt.Errorf("extension %d/%s: %w", extIdx, oidStr, err)) } } + out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, 0, len(out.Policies)) + for _, oid := range out.Policies { + if oid, ok := oid.toASN1OID(); ok { + out.PolicyIdentifiers = append(out.PolicyIdentifiers, oid) + } + } + case 33: + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid policy mappings extension") + } + for !val.Empty() { + var s cryptobyte.String + var issuer, subject cryptobyte.String + if !val.ReadASN1(&s, cryptobyte_asn1.SEQUENCE) || + !s.ReadASN1(&issuer, cryptobyte_asn1.OBJECT_IDENTIFIER) || + !s.ReadASN1(&subject, cryptobyte_asn1.OBJECT_IDENTIFIER) { + return errors.New("x509: invalid policy mappings extension") + } + out.PolicyMappings = append(out.PolicyMappings, PolicyMapping{OID{issuer}, OID{subject}}) + } + case 54: + val := cryptobyte.String(e.Value) + if !val.ReadASN1Integer(&out.InhibitAnyPolicy) { + return errors.New("x509: invalid inhibit any policy extension") + } + out.InhibitAnyPolicyZero = out.InhibitAnyPolicy == 0 default: // Unknown extensions are recorded if critical. unhandled = true @@ -965,8 +1102,12 @@ func processExtensions(out *Certificate) error { } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { // RFC 5280 4.2.2.1: Authority Information Access if e.Critical { - // Conforming CAs MUST mark this extension as non-critical - return errors.New("x509: authority info access incorrectly marked critical") + err := errors.New("x509: authority info access incorrectly marked critical") + if !asn1.AllowPermissiveParsing { + return err + } else { + out.PermissiveErrors = append(out.PermissiveErrors, fmt.Errorf("extension %d/%s: %w", extIdx, oidStr, err)) + } } val := cryptobyte.String(e.Value) if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { @@ -1121,6 +1262,7 @@ func parseCertificate(in *certificate) (*Certificate, error) { // Process the certificate input := cryptobyte.String(in.Raw) + // we read the SEQUENCE including length and tag bytes so that // we can populate Certificate.Raw, before unwrapping the // SEQUENCE so it can be operated on diff --git a/crypto/x509/parser_test.go b/crypto/x509/parser_test.go index 81fdebe34ae..5ce2575aada 100644 --- a/crypto/x509/parser_test.go +++ b/crypto/x509/parser_test.go @@ -5,6 +5,8 @@ package x509 import ( + "encoding/pem" + "os" "testing" "github.com/runZeroInc/excrypto/encoding/asn1" @@ -13,6 +15,10 @@ import ( ) func TestParseASN1String(t *testing.T) { + // Disable permissive parsing for this test + oValue := asn1.AllowPermissiveParsing + asn1.AllowPermissiveParsing = false + defer func() { asn1.AllowPermissiveParsing = oValue }() tests := []struct { name string tag cryptobyte_asn1.Tag @@ -23,8 +29,8 @@ func TestParseASN1String(t *testing.T) { { name: "T61String", tag: cryptobyte_asn1.T61String, - value: []byte{80, 81, 82}, - expected: string("PQR"), + value: []byte{0xbf, 0x61, 0x3f}, + expected: string("¿a?"), }, { name: "PrintableString", @@ -62,6 +68,30 @@ func TestParseASN1String(t *testing.T) { value: []byte{255}, expectedErr: "invalid BMPString", }, + { + name: "BMPString (invalid surrogate)", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{80, 81, 216, 1}, + expectedErr: "invalid BMPString", + }, + { + name: "BMPString (invalid noncharacter 0xfdd1)", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{80, 81, 253, 209}, + expectedErr: "invalid BMPString", + }, + { + name: "BMPString (invalid noncharacter 0xffff)", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{80, 81, 255, 255}, + expectedErr: "invalid BMPString", + }, + { + name: "BMPString (invalid noncharacter 0xfffe)", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{80, 81, 255, 254}, + expectedErr: "invalid BMPString", + }, { name: "IA5String", tag: cryptobyte_asn1.IA5String, @@ -69,10 +99,10 @@ func TestParseASN1String(t *testing.T) { expected: string("PQ"), }, { - name: "IA5String (invalid)", - tag: cryptobyte_asn1.IA5String, - value: []byte{255}, - expected: string("\xff"), // zcrypto: allow invalid strings + name: "IA5String (invalid)", + tag: cryptobyte_asn1.IA5String, + value: []byte{255}, + expectedErr: "invalid IA5String", }, { name: "NumericString", @@ -102,3 +132,127 @@ func TestParseASN1String(t *testing.T) { }) } } + +const policyPEM = `-----BEGIN CERTIFICATE----- +MIIGeDCCBWCgAwIBAgIUED9KQBi0ScBDoufB2mgAJ63G5uIwDQYJKoZIhvcNAQEL +BQAwVTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG +A1UECxMERlBLSTEdMBsGA1UEAxMURmVkZXJhbCBCcmlkZ2UgQ0EgRzQwHhcNMjAx +MDIyMTcwNDE5WhcNMjMxMDIyMTcwNDE5WjCBgTELMAkGA1UEBhMCVVMxHTAbBgNV +BAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVz +dCBOZXR3b3JrMTIwMAYDVQQDEylTeW1hbnRlYyBDbGFzcyAzIFNTUCBJbnRlcm1l +ZGlhdGUgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2p +75cMpx86sS2aH4r+0o8r+m/KTrPrknWP0RA9Kp6sewAzkNa7BVwg0jOhyamiv1iP +Cns10usoH93nxYbXLWF54vOLRdYU/53KEPNmgkj2ipMaTLuaReBghNibikWSnAmy +S8RItaDMs8tdF2goKPI4xWiamNwqe92VC+pic2tq0Nva3Y4kvMDJjtyje3uduTtL +oyoaaHkrX7i7gE67psnMKj1THUtre1JV1ohl9+oOuyot4p3eSxVlrMWiiwb11bnk +CakecOz/mP2DHMGg6pZ/BeJ+ThaLUylAXECARIqHc9UwRPKC9BfLaCX4edIoeYiB +loRs4KdqLdg/I9eTwKkCAwEAAaOCAxEwggMNMB0GA1UdDgQWBBQ1Jn1QleGhwb0F +1cOdd0LHDBOWjDAfBgNVHSMEGDAWgBR58ABJ6393wl1BAmU0ipAjmx4HbzAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBiAYDVR0gBIGAMH4wDAYKYIZI +AWUDAgEDAzAMBgpghkgBZQMCAQMMMAwGCmCGSAFlAwIBAw4wDAYKYIZIAWUDAgED +DzAMBgpghkgBZQMCAQMSMAwGCmCGSAFlAwIBAxMwDAYKYIZIAWUDAgEDFDAMBgpg +hkgBZQMCAQMlMAwGCmCGSAFlAwIBAyYwggESBgNVHSEEggEJMIIBBTAbBgpghkgB +ZQMCAQMDBg1ghkgBhvhFAQcXAwEGMBsGCmCGSAFlAwIBAwwGDWCGSAGG+EUBBxcD +AQcwGwYKYIZIAWUDAgEDDgYNYIZIAYb4RQEHFwMBDjAbBgpghkgBZQMCAQMPBg1g +hkgBhvhFAQcXAwEPMBsGCmCGSAFlAwIBAxIGDWCGSAGG+EUBBxcDARIwGwYKYIZI +AWUDAgEDEwYNYIZIAYb4RQEHFwMBETAbBgpghkgBZQMCAQMUBg1ghkgBhvhFAQcX +AwEUMBsGCmCGSAFlAwIBAyUGDWCGSAGG+EUBBxcDAQgwGwYKYIZIAWUDAgEDJgYN +YIZIAYb4RQEHFwMBJDBgBggrBgEFBQcBCwRUMFIwUAYIKwYBBQUHMAWGRGh0dHA6 +Ly9zc3Atc2lhLnN5bWF1dGguY29tL1NUTlNTUC9DZXJ0c19Jc3N1ZWRfYnlfQ2xh +c3MzU1NQQ0EtRzMucDdjMA8GA1UdJAQIMAaAAQCBAQAwCgYDVR02BAMCAQAwUQYI +KwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVodHRwOi8vcmVwby5mcGtpLmdvdi9i +cmlkZ2UvY2FDZXJ0c0lzc3VlZFRvZmJjYWc0LnA3YzA3BgNVHR8EMDAuMCygKqAo +hiZodHRwOi8vcmVwby5mcGtpLmdvdi9icmlkZ2UvZmJjYWc0LmNybDANBgkqhkiG +9w0BAQsFAAOCAQEAA751TycC1f/WTkHmedF9ZWxP58Jstmwvkyo8bKueJ0eF7LTG +BgQlzE2B9vke4sFhd4V+BdgOPGE1dsGzllYKCWg0BhkCBs5kIJ7F6Ay6G1TBuGU1 +Ie8247GL+P9pcC5TVvXHC/62R2w3DuD/vAPLbYEbSQjobXlsqt8Kmtd6yK/jVuDV +BTZMdZmvoNtjemqmgcBXHsf0ctVm0m6tH5uYqyVxu8tfyUis6Cf303PHj+spWP1k +gc5PYnVF0ot7qAmNFENIpbKg3BdusBkF9rGxLaDSUBvSc7+s9iQz9d/iRuAebrYu ++eqUlJ2lsjS1U8qyPmlH+spfPNbAEQEsuP32Aw== +-----END CERTIFICATE----- +` + +func TestPolicyParse(t *testing.T) { + b, _ := pem.Decode([]byte(policyPEM)) + c, err := ParseCertificate(b.Bytes) + if err != nil { + t.Fatal(err) + } + if len(c.Policies) != 9 { + t.Errorf("unexpected number of policies: got %d, want %d", len(c.Policies), 9) + } + if len(c.PolicyMappings) != 9 { + t.Errorf("unexpected number of policy mappings: got %d, want %d", len(c.PolicyMappings), 9) + } + if !c.RequireExplicitPolicyZero { + t.Error("expected RequireExplicitPolicyZero to be set") + } + if !c.InhibitPolicyMappingZero { + t.Error("expected InhibitPolicyMappingZero to be set") + } + if !c.InhibitAnyPolicyZero { + t.Error("expected InhibitAnyPolicyZero to be set") + } +} + +func TestParsePolicies(t *testing.T) { + for _, tc := range []string{ + "testdata/policy_leaf_duplicate.pem", + "testdata/policy_leaf_invalid.pem", + } { + t.Run(tc, func(t *testing.T) { + b, err := os.ReadFile(tc) + if err != nil { + t.Fatal(err) + } + p, _ := pem.Decode(b) + _, err = ParseCertificate(p.Bytes) + if err == nil { + t.Error("parsing should've failed") + } + }) + } +} + +func TestParseCertificateNegativeMaxPathLength(t *testing.T) { + certs := []string{ + // Certificate with MaxPathLen set to -1. + ` +-----BEGIN CERTIFICATE----- +MIIByTCCATKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRURVNU +MB4XDTcwMDEwMTAwMTY0MFoXDTcwMDEwMjAzNDY0MFowDzENMAsGA1UEAxMEVEVT +VDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsaHglFuSicTT8TKfipgsSi3N +Wb/TcvuAhanFF1VGB+vS95kO7yFqyfRgX3GgOwT0KlJVsVjPjghEGR9RGTSLqkTD +UFbiBgm8+VEPMOrUtIHIHXhl+ye44AkOEStxfz7gjN/EAS2h8ffPKhvDTHOlShKw +Y3LQlxR0LdeJXq3eSqUCAwEAAaM1MDMwEgYDVR0TAQH/BAgwBgEB/wIB/zAdBgNV +HQ4EFgQUrbrk0tqQAEsce8uYifP0BIVhuFAwDQYJKoZIhvcNAQELBQADgYEAIkhV +ZBj1ThT+eyh50XsoU570NUysTg3Nj/3lbkEolzdcE+wu0CPXvgxLRM6Y62u1ey82 +8d5VQHstzF4dXgc3W+O9UySa+CKdcHx/q7o7seOGXdysT0IJtAY3w66mFkuF7PIn +y9b7M5t6pmWjb7N0QqGuWeNqi4ZvS8gLKmVEgGY= +-----END CERTIFICATE----- +`, + // Certificate with MaxPathLen set to -2. + ` +-----BEGIN CERTIFICATE----- +MIIByTCCATKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRURVNU +MB4XDTcwMDEwMTAwMTY0MFoXDTcwMDEwMjAzNDY0MFowDzENMAsGA1UEAxMEVEVT +VDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsaHglFuSicTT8TKfipgsSi3N +Wb/TcvuAhanFF1VGB+vS95kO7yFqyfRgX3GgOwT0KlJVsVjPjghEGR9RGTSLqkTD +UFbiBgm8+VEPMOrUtIHIHXhl+ye44AkOEStxfz7gjN/EAS2h8ffPKhvDTHOlShKw +Y3LQlxR0LdeJXq3eSqUCAwEAAaM1MDMwEgYDVR0TAQH/BAgwBgEB/wIB/jAdBgNV +HQ4EFgQUrbrk0tqQAEsce8uYifP0BIVhuFAwDQYJKoZIhvcNAQELBQADgYEAGjIr +YGQc7Ods+BuKck7p+vpAMONM8SLEuUtKorCP3ecsO51MoA4/niLbgMHaOGNHwzMp +ajg0zLbY0Dj6Ml0VZ+lS3rjgTEhYXc626eZkoQqgUzL1jhe3S0ZbSxxmHMBKjJFl +d5l1tRhScKu2NBgm74nYmJxJYgvuTA38wGhRrGU= +-----END CERTIFICATE----- +`, + } + + for _, cert := range certs { + b, _ := pem.Decode([]byte(cert)) + _, err := ParseCertificate(b.Bytes) + if err == nil || err.Error() != "x509: invalid basic constraints" { + t.Errorf(`ParseCertificate() = %v; want = "x509: invalid basic constraints"`, err) + } + } +} diff --git a/crypto/x509/pem_decrypt_test.go b/crypto/x509/pem_decrypt_test.go index 9657ad45fae..dacef8b8617 100644 --- a/crypto/x509/pem_decrypt_test.go +++ b/crypto/x509/pem_decrypt_test.go @@ -6,12 +6,11 @@ package x509 import ( "bytes" + "crypto/rand" "encoding/base64" "encoding/pem" "strings" "testing" - - "crypto/rand" ) func TestDecrypt(t *testing.T) { diff --git a/crypto/x509/performance_test.go b/crypto/x509/performance_test.go deleted file mode 100644 index 59797cc0a25..00000000000 --- a/crypto/x509/performance_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package x509 - -import ( - "encoding/json" - "encoding/pem" - "os" - "testing" -) - -func BenchmarkParse(b *testing.B) { - fileBytes, _ := os.ReadFile("testdata/davidadrian.org.cert") - p, _ := pem.Decode(fileBytes) - for i := 0; i < b.N; i++ { - ParseCertificate(p.Bytes) - } -} - -func BenchmarkEncode(b *testing.B) { - fileBytes, _ := os.ReadFile("testdata/davidadrian.org.cert") - p, _ := pem.Decode(fileBytes) - c, _ := ParseCertificate(p.Bytes) - for i := 0; i < b.N; i++ { - json.Marshal(c) - } -} diff --git a/crypto/x509/pkcs1.go b/crypto/x509/pkcs1.go index 86d99e6f938..a1487f537f0 100644 --- a/crypto/x509/pkcs1.go +++ b/crypto/x509/pkcs1.go @@ -10,6 +10,7 @@ import ( "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/encoding/asn1" + "github.com/runZeroInc/excrypto/internal/godebug" ) // pkcs1PrivateKey is a structure which mirrors the PKCS #1 ASN.1 for an RSA private key. @@ -20,10 +21,9 @@ type pkcs1PrivateKey struct { D *big.Int P *big.Int Q *big.Int - // We ignore these values, if present, because rsa will calculate them. - Dp *big.Int `asn1:"optional"` - Dq *big.Int `asn1:"optional"` - Qinv *big.Int `asn1:"optional"` + Dp *big.Int `asn1:"optional"` + Dq *big.Int `asn1:"optional"` + Qinv *big.Int `asn1:"optional"` AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"` } @@ -42,9 +42,16 @@ type pkcs1PublicKey struct { E int } +// x509rsacrt, if zero, makes ParsePKCS1PrivateKey ignore and recompute invalid +// CRT values in the RSA private key. +var x509rsacrt = godebug.New("x509rsacrt") + // ParsePKCS1PrivateKey parses an [RSA] private key in PKCS #1, ASN.1 DER form. // // This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". +// +// Before Go 1.24, the CRT parameters were ignored and recomputed. To restore +// the old behavior, use the GODEBUG=x509rsacrt=0 environment variable. func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { var priv pkcs1PrivateKey rest, err := asn1.Unmarshal(der, &priv) @@ -65,7 +72,10 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { return nil, errors.New("x509: unsupported private key version") } - if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { + if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 || + priv.Dp != nil && priv.Dp.Sign() <= 0 || + priv.Dq != nil && priv.Dq.Sign() <= 0 || + priv.Qinv != nil && priv.Qinv.Sign() <= 0 { return nil, errors.New("x509: private key contains zero or negative value") } @@ -79,6 +89,9 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) key.Primes[0] = priv.P key.Primes[1] = priv.Q + key.Precomputed.Dp = priv.Dp + key.Precomputed.Dq = priv.Dq + key.Precomputed.Qinv = priv.Qinv for i, a := range priv.AdditionalPrimes { if a.Prime.Sign() <= 0 { return nil, errors.New("x509: private key contains zero or negative prime") @@ -88,11 +101,23 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { // them as needed. } - err = key.Validate() - if err != nil { + key.Precompute() + if err := key.Validate(); err != nil { + // If x509rsacrt=0 is set, try dropping the CRT values and + // rerunning precomputation and key validation. + if x509rsacrt.Value() == "0" { + key.Precomputed.Dp = nil + key.Precomputed.Dq = nil + key.Precomputed.Qinv = nil + key.Precompute() + if err := key.Validate(); err == nil { + x509rsacrt.IncNonDefault() + return key, nil + } + } + return nil, err } - key.Precompute() return key, nil } @@ -102,6 +127,10 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { // This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". // For a more flexible key format which is not [RSA] specific, use // [MarshalPKCS8PrivateKey]. +// +// The key must have passed validation by calling [rsa.PrivateKey.Validate] +// first. MarshalPKCS1PrivateKey calls [rsa.PrivateKey.Precompute], which may +// modify the key if not already precomputed. func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { key.Precompute() diff --git a/crypto/x509/pkcs8.go b/crypto/x509/pkcs8.go index fd88501f7d2..8b40bbb8316 100644 --- a/crypto/x509/pkcs8.go +++ b/crypto/x509/pkcs8.go @@ -33,6 +33,9 @@ type pkcs8 struct { // in the future. // // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". +// +// Before Go 1.24, the CRT parameters of RSA keys were ignored and recomputed. +// To restore the old behavior, use the GODEBUG=x509rsacrt=0 environment variable. func ParsePKCS8PrivateKey(der []byte) (key any, err error) { var privKey pkcs8 if _, err := asn1.Unmarshal(der, &privKey); err != nil { @@ -99,6 +102,8 @@ func ParsePKCS8PrivateKey(der []byte) (key any, err error) { // Unsupported key types result in an error. // // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". +// +// MarshalPKCS8PrivateKey runs [rsa.PrivateKey.Precompute] on RSA keys. func MarshalPKCS8PrivateKey(key any) ([]byte, error) { var privKey pkcs8 @@ -108,6 +113,10 @@ func MarshalPKCS8PrivateKey(key any) ([]byte, error) { Algorithm: oidPublicKeyRSA, Parameters: asn1.NullRawValue, } + k.Precompute() + if err := k.Validate(); err != nil { + return nil, err + } privKey.PrivateKey = MarshalPKCS1PrivateKey(k) case *ecdsa.PrivateKey: diff --git a/crypto/x509/pkits_test.go b/crypto/x509/pkits_test.go new file mode 100644 index 00000000000..b1139bbf9c6 --- /dev/null +++ b/crypto/x509/pkits_test.go @@ -0,0 +1,186 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "encoding/json" + "os" + "path/filepath" + "slices" + "testing" +) + +var nistTestPolicies = map[string]OID{ + "anyPolicy": anyPolicyOID, + "NIST-test-policy-1": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 1}), + "NIST-test-policy-2": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 2}), + "NIST-test-policy-3": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 3}), + "NIST-test-policy-6": mustNewOIDFromInts([]uint64{2, 16, 840, 1, 101, 3, 2, 1, 48, 6}), +} + +func TestNISTPKITSPolicy(t *testing.T) { + // This test runs a subset of the NIST PKI path validation test suite that + // focuses of policy validation, rather than the entire suite. Since the + // suite assumes you are only validating the path, rather than building + // _and_ validating the path, we take the path as given and run + // policiesValid on it. + + certDir := "testdata/nist-pkits/certs" + + var testcases []struct { + Name string + CertPath []string + InitialPolicySet []string + InitialPolicyMappingInhibit bool + InitialExplicitPolicy bool + InitialAnyPolicyInhibit bool + ShouldValidate bool + Skipped bool + } + b, err := os.ReadFile("testdata/nist-pkits/vectors.json") + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(b, &testcases); err != nil { + t.Fatal(err) + } + + policyTests := map[string]bool{ + "4.8.1 All Certificates Same Policy Test1 (Subpart 1)": true, + "4.8.1 All Certificates Same Policy Test1 (Subpart 2)": true, + "4.8.1 All Certificates Same Policy Test1 (Subpart 3)": true, + "4.8.1 All Certificates Same Policy Test1 (Subpart 4)": true, + "4.8.2 All Certificates No Policies Test2 (Subpart 1)": true, + "4.8.2 All Certificates No Policies Test2 (Subpart 2)": true, + "4.8.3 Different Policies Test3 (Subpart 1)": true, + "4.8.3 Different Policies Test3 (Subpart 2)": true, + "4.8.3 Different Policies Test3 (Subpart 3)": true, + "4.8.4 Different Policies Test4": true, + "4.8.5 Different Policies Test5": true, + "4.8.6 Overlapping Policies Test6 (Subpart 1)": true, + "4.8.6 Overlapping Policies Test6 (Subpart 2)": true, + "4.8.6 Overlapping Policies Test6 (Subpart 3)": true, + "4.8.7 Different Policies Test7": true, + "4.8.8 Different Policies Test8": true, + "4.8.9 Different Policies Test9": true, + "4.8.10 All Certificates Same Policies Test10 (Subpart 1)": true, + "4.8.10 All Certificates Same Policies Test10 (Subpart 2)": true, + "4.8.10 All Certificates Same Policies Test10 (Subpart 3)": true, + "4.8.11 All Certificates AnyPolicy Test11 (Subpart 1)": true, + "4.8.11 All Certificates AnyPolicy Test11 (Subpart 2)": true, + "4.8.12 Different Policies Test12": true, + "4.8.13 All Certificates Same Policies Test13 (Subpart 1)": true, + "4.8.13 All Certificates Same Policies Test13 (Subpart 2)": true, + "4.8.13 All Certificates Same Policies Test13 (Subpart 3)": true, + "4.8.14 AnyPolicy Test14 (Subpart 1)": true, + "4.8.14 AnyPolicy Test14 (Subpart 2)": true, + "4.8.15 User Notice Qualifier Test15": true, + "4.8.16 User Notice Qualifier Test16": true, + "4.8.17 User Notice Qualifier Test17": true, + "4.8.18 User Notice Qualifier Test18 (Subpart 1)": true, + "4.8.18 User Notice Qualifier Test18 (Subpart 2)": true, + "4.8.19 User Notice Qualifier Test19": true, + "4.8.20 CPS Pointer Qualifier Test20": true, + "4.9.1 Valid RequireExplicitPolicy Test1": true, + "4.9.2 Valid RequireExplicitPolicy Test2": true, + "4.9.3 Invalid RequireExplicitPolicy Test3": true, + "4.9.4 Valid RequireExplicitPolicy Test4": true, + "4.9.5 Invalid RequireExplicitPolicy Test5": true, + "4.9.6 Valid Self-Issued requireExplicitPolicy Test6": true, + "4.9.7 Invalid Self-Issued requireExplicitPolicy Test7": true, + "4.9.8 Invalid Self-Issued requireExplicitPolicy Test8": true, + "4.10.1.1 Valid Policy Mapping Test1 (Subpart 1)": true, + "4.10.1.2 Valid Policy Mapping Test1 (Subpart 2)": true, + "4.10.1.3 Valid Policy Mapping Test1 (Subpart 3)": true, + "4.10.2 Invalid Policy Mapping Test2 (Subpart 1)": true, + "4.10.2 Invalid Policy Mapping Test2 (Subpart 2)": true, + "4.10.3 Valid Policy Mapping Test3 (Subpart 1)": true, + "4.10.3 Valid Policy Mapping Test3 (Subpart 2)": true, + "4.10.4 Invalid Policy Mapping Test4": true, + "4.10.5 Valid Policy Mapping Test5 (Subpart 1)": true, + "4.10.5 Valid Policy Mapping Test5 (Subpart 2)": true, + "4.10.6 Valid Policy Mapping Test6 (Subpart 1)": true, + "4.10.6 Valid Policy Mapping Test6 (Subpart 2)": true, + "4.10.7 Invalid Mapping From anyPolicy Test7": true, + "4.10.8 Invalid Mapping To anyPolicy Test8": true, + "4.10.9 Valid Policy Mapping Test9": true, + "4.10.10 Invalid Policy Mapping Test10": true, + "4.10.11 Valid Policy Mapping Test11": true, + "4.10.12 Valid Policy Mapping Test12 (Subpart 1)": true, + "4.10.12 Valid Policy Mapping Test12 (Subpart 2)": true, + "4.10.13 Valid Policy Mapping Test13 (Subpart 1)": true, + "4.10.13 Valid Policy Mapping Test13 (Subpart 2)": true, + "4.10.13 Valid Policy Mapping Test13 (Subpart 3)": true, + "4.10.14 Valid Policy Mapping Test14": true, + "4.11.1 Invalid inhibitPolicyMapping Test1": true, + "4.11.2 Valid inhibitPolicyMapping Test2": true, + "4.11.3 Invalid inhibitPolicyMapping Test3": true, + "4.11.4 Valid inhibitPolicyMapping Test4": true, + "4.11.5 Invalid inhibitPolicyMapping Test5": true, + "4.11.6 Invalid inhibitPolicyMapping Test6": true, + "4.11.7 Valid Self-Issued inhibitPolicyMapping Test7": true, + "4.11.8 Invalid Self-Issued inhibitPolicyMapping Test8": true, + "4.11.9 Invalid Self-Issued inhibitPolicyMapping Test9": true, + "4.11.10 Invalid Self-Issued inhibitPolicyMapping Test10": true, + "4.11.11 Invalid Self-Issued inhibitPolicyMapping Test11": true, + "4.12.1 Invalid inhibitAnyPolicy Test1": true, + "4.12.2 Valid inhibitAnyPolicy Test2": true, + "4.12.3 inhibitAnyPolicy Test3 (Subpart 1)": true, + "4.12.3 inhibitAnyPolicy Test3 (Subpart 2)": true, + "4.12.4 Invalid inhibitAnyPolicy Test4": true, + "4.12.5 Invalid inhibitAnyPolicy Test5": true, + "4.12.6 Invalid inhibitAnyPolicy Test6": true, + "4.12.7 Valid Self-Issued inhibitAnyPolicy Test7": true, + "4.12.8 Invalid Self-Issued inhibitAnyPolicy Test8": true, + "4.12.9 Valid Self-Issued inhibitAnyPolicy Test9": true, + "4.12.10 Invalid Self-Issued inhibitAnyPolicy Test10": true, + } + + for _, tc := range testcases { + if !policyTests[tc.Name] { + continue + } + t.Run(tc.Name, func(t *testing.T) { + var chain []*Certificate + for _, c := range tc.CertPath { + certDER, err := os.ReadFile(filepath.Join(certDir, c)) + if err != nil { + t.Fatal(err) + } + cert, err := ParseCertificate(certDER) + if err != nil { + t.Fatal(err) + } + chain = append(chain, cert) + } + slices.Reverse(chain) + + var initialPolicies []OID + for _, pstr := range tc.InitialPolicySet { + policy, ok := nistTestPolicies[pstr] + if !ok { + t.Fatalf("unknown test policy: %s", pstr) + } + initialPolicies = append(initialPolicies, policy) + } + + valid := policiesValid(chain, VerifyOptions{ + CertificatePolicies: initialPolicies, + inhibitPolicyMapping: tc.InitialPolicyMappingInhibit, + requireExplicitPolicy: tc.InitialExplicitPolicy, + inhibitAnyPolicy: tc.InitialAnyPolicyInhibit, + }) + if !valid { + if !tc.ShouldValidate { + return + } + t.Fatalf("Failed to validate: %s", err) + } + if !tc.ShouldValidate { + t.Fatal("Expected path validation to fail") + } + }) + } +} diff --git a/crypto/x509/pkix/pkix.go b/crypto/x509/pkix/pkix.go index cf95bfe013d..9b855912f1a 100644 --- a/crypto/x509/pkix/pkix.go +++ b/crypto/x509/pkix/pkix.go @@ -16,11 +16,6 @@ import ( "github.com/runZeroInc/excrypto/encoding/asn1" ) -// zcrypto -// LegacyNameString allows to specify legacy ZCrypto behaviour -// for X509Name.String() in reverse order -var LegacyNameString = false - // AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC // 5280, section 4.1.1.2. type AlgorithmIdentifier struct { @@ -32,29 +27,22 @@ type RDNSequence []RelativeDistinguishedNameSET // String returns a string representation of the sequence r, // roughly following the RFC 2253 Distinguished Names syntax. -// zcrypto func (r RDNSequence) String() string { s := "" for i := 0; i < len(r); i++ { - idx := len(r) - 1 - i - if LegacyNameString { - idx = i - } - rdn := r[idx] + rdn := r[len(r)-1-i] if i > 0 { - s += ", " + s += "," } for j, tv := range rdn { if j > 0 { - s += ", " + s += "+" } - oidString := tv.Type.String() var typeName string - if oidName, ok := oidDotNotationToNames[oidString]; ok { - typeName = oidName.ShortName - } - if typeName == "" { + oidString := tv.Type.String() + typeNameRaw, ok := oidDotNotationToNames[oidString] + if !ok { derBytes, err := asn1.Marshal(tv.Value) if err == nil { s += oidString + "=#" + hex.EncodeToString(derBytes) @@ -62,6 +50,8 @@ func (r RDNSequence) String() string { } typeName = oidString + } else { + typeName = typeNameRaw.ShortName } valueString := fmt.Sprint(tv.Value) @@ -100,8 +90,8 @@ type RelativeDistinguishedNameSET []AttributeTypeAndValue // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in // RFC 5280, Section 4.1.2.4. type AttributeTypeAndValue struct { - Type asn1.ObjectIdentifier `json:"type"` - Value interface{} `json:"value"` + Type asn1.ObjectIdentifier + Value any } // AttributeTypeAndValueSET represents a set of ASN.1 sequences of @@ -242,10 +232,8 @@ var ( // attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and // search for AttributeTypeAndValue. func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence { - // zcrypto - // NOTE: stdlib prevents adding if the oid is already present in n.ExtraNames - // if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) { - if len(values) == 0 { + // TODO: excrypto should enable an override here, this breaks ExtraName replacement of things like Country + if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) { return in } @@ -274,16 +262,13 @@ func (n Name) ToRDNSequence() (ret RDNSequence) { if n.OriginalRDNS != nil { return n.OriginalRDNS } - if len(n.CommonName) > 0 { - ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName) - } - ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit) - ret = n.appendRDNs(ret, n.Organization, oidOrganization) - ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress) - ret = n.appendRDNs(ret, n.Locality, oidLocality) + ret = n.appendRDNs(ret, n.Country, oidCountry) ret = n.appendRDNs(ret, n.Province, oidProvince) + ret = n.appendRDNs(ret, n.Locality, oidLocality) + ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress) ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode) - ret = n.appendRDNs(ret, n.Country, oidCountry) + ret = n.appendRDNs(ret, n.Organization, oidOrganization) + ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit) ret = n.appendRDNs(ret, n.DomainComponent, oidDomainComponent) // EV Components ret = n.appendRDNs(ret, n.JurisdictionLocality, oidJurisdictionLocality) @@ -291,6 +276,9 @@ func (n Name) ToRDNSequence() (ret RDNSequence) { ret = n.appendRDNs(ret, n.JurisdictionCountry, oidJurisdictionCountry) // QWACS ret = n.appendRDNs(ret, n.OrganizationIDs, oidOrganizationID) + if len(n.CommonName) > 0 { + ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName) + } if len(n.SerialNumber) > 0 { ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber) } @@ -300,20 +288,6 @@ func (n Name) ToRDNSequence() (ret RDNSequence) { return ret } -// CertificateList represents the ASN.1 structure of the same name. See RFC -// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the -// signature. -type CertificateList struct { - TBSCertList TBSCertificateList - SignatureAlgorithm AlgorithmIdentifier - SignatureValue asn1.BitString -} - -// HasExpired reports whether certList should have been updated by now. -func (certList *CertificateList) HasExpired(now time.Time) bool { - return !now.Before(certList.TBSCertList.NextUpdate) -} - // String returns the string form of n, roughly following // the RFC 2253 Distinguished Names syntax. func (n Name) String() string { @@ -377,8 +351,26 @@ func oidValueAlreadyInAttributeTypeAndValue(in RDNSequence, oid asn1.ObjectIdent return false } +// CertificateList represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the +// signature. +// +// Deprecated: x509.RevocationList should be used instead. +type CertificateList struct { + TBSCertList TBSCertificateList + SignatureAlgorithm AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// HasExpired reports whether certList should have been updated by now. +func (certList *CertificateList) HasExpired(now time.Time) bool { + return !now.Before(certList.TBSCertList.NextUpdate) +} + // TBSCertificateList represents the ASN.1 structure of the same name. See RFC // 5280, section 5.1. +// +// Deprecated: x509.RevocationList should be used instead. type TBSCertificateList struct { Raw asn1.RawContent Version int `asn1:"optional,default:0"` diff --git a/crypto/x509/pkix/pkix_test.go b/crypto/x509/pkix/pkix_test.go deleted file mode 100644 index 8e78d8ff649..00000000000 --- a/crypto/x509/pkix/pkix_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pkix - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNameString(t *testing.T) { - tests := []struct { - name Name - expected string - legacy string - }{ - { - name: Name{}, - expected: "", - legacy: "", - }, - { - name: Name{ - SerialNumber: "12345", - CommonName: "common", - Country: []string{"US", "RU"}, - Organization: []string{"University of Michigan"}, - OrganizationalUnit: []string{"0x21"}, - Locality: []string{"Ann Arbor"}, - Province: []string{"Michigan"}, - StreetAddress: []string{"2260 Hayward St"}, - PostalCode: []string{"48109"}, - DomainComponent: nil, - ExtraNames: []AttributeTypeAndValue{{Type: oidCommonName, Value: "name"}, {Type: oidSerialNumber, Value: "67890"}}, - }, - expected: "SERIALNUMBER=67890, CN=name, SERIALNUMBER=12345, C=US, C=RU, POSTALCODE=48109, ST=Michigan, L=Ann Arbor, STREET=2260 Hayward St, O=University of Michigan, OU=0x21, CN=common", - legacy: "CN=common, OU=0x21, O=University of Michigan, STREET=2260 Hayward St, L=Ann Arbor, ST=Michigan, POSTALCODE=48109, C=US, C=RU, SERIALNUMBER=12345, CN=name, SERIALNUMBER=67890", - }, - { - name: Name{ - SerialNumber: "12345", - CommonName: "common", - PostalCode: []string{"48109"}, - OriginalRDNS: RDNSequence{ - []AttributeTypeAndValue{ - {Type: oidPostalCode, Value: "48109"}, - {Type: oidSerialNumber, Value: "12345"}, - {Type: oidCommonName, Value: "common"}, - {Type: oidGivenName, Value: "given"}, - {Type: oidDomainComponent, Value: "domain"}, - {Type: oidDNEmailAddress, Value: "user@dn.com"}, - {Type: oidJurisdictionLocality, Value: "Locality"}, - {Type: oidJurisdictionProvince, Value: "Prov"}, - {Type: oidJurisdictionCountry, Value: "Canada"}, - {Type: oidOrganizationID, Value: "QWACS"}, - }, - }, - }, - expected: "POSTALCODE=48109, SERIALNUMBER=12345, CN=common, GN=given, DC=domain, emailAddress=user@dn.com, jurisdictionLocality=Locality, jurisdictionStateOrProvince=Prov, jurisdictionCountry=Canada, organizationIdentifier=QWACS", - legacy: "POSTALCODE=48109, SERIALNUMBER=12345, CN=common, GN=given, DC=domain, emailAddress=user@dn.com, jurisdictionLocality=Locality, jurisdictionStateOrProvince=Prov, jurisdictionCountry=Canada, organizationIdentifier=QWACS", - }, - } - for _, test := range tests { - s := test.name.String() - assert.Equal(t, test.expected, s) - } - LegacyNameString = true - for _, test := range tests { - s := test.name.String() - assert.Equal(t, test.legacy, s) - } -} diff --git a/crypto/x509/platform_test.go b/crypto/x509/platform_test.go index 48287abe73c..a167577a5d3 100644 --- a/crypto/x509/platform_test.go +++ b/crypto/x509/platform_test.go @@ -5,6 +5,7 @@ package x509 import ( + "crypto/rand" "encoding/pem" "math/big" "os" @@ -13,8 +14,6 @@ import ( "testing" "time" - "crypto/rand" - "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" ) diff --git a/crypto/x509/revocation/crl/crl.go b/crypto/x509/revocation/crl/crl.go deleted file mode 100644 index b8a54932a4f..00000000000 --- a/crypto/x509/revocation/crl/crl.go +++ /dev/null @@ -1,159 +0,0 @@ -package crl - -import ( - "encoding/json" - "time" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/encoding/asn1" -) - -// RevocationReasonCode - status codes that explain revocation reason see RFC 5280, Section 5.3.1 -type RevocationReasonCode int - -var reasonCodeNames map[RevocationReasonCode]string - -func init() { - reasonCodeNames = make(map[RevocationReasonCode]string) - reasonCodeNames[0] = "unspecified" - reasonCodeNames[1] = "keyCompromise" - reasonCodeNames[2] = "cACompromise" - reasonCodeNames[3] = "affiliationChanged" - reasonCodeNames[4] = "superseded" - reasonCodeNames[5] = "cessationOfOperation" - reasonCodeNames[6] = "certificateHold" - // STATUS CODE 7 IS NOT USED - reasonCodeNames[8] = "removeFromCRL" - reasonCodeNames[9] = "privilegeWithdrawn" - reasonCodeNames[10] = "aACompromise" -} - -// MarshalJSON implements the json.Marshler interface -func (code *RevocationReasonCode) MarshalJSON() ([]byte, error) { - aux := struct { - Value int `json:"value"` - Name string `json:"name"` - }{ - Value: int(*code), - Name: code.String(), - } - return json.Marshal(&aux) -} - -// UnmarshalJSON implements the json.Unmarshaler interface -func (code *RevocationReasonCode) UnmarshalJSON(b []byte) error { - aux := struct { - Value int `json:"value"` - Name string `json:"name"` - }{} - if err := json.Unmarshal(b, &aux); err != nil { - return err - } - *code = RevocationReasonCode(aux.Value) - return nil -} - -func (code *RevocationReasonCode) String() string { - return reasonCodeNames[*code] -} - -var ( - crlNumberExtensionOID = asn1.ObjectIdentifier{2, 5, 29, 20} - revocationReasonExtensionOID = asn1.ObjectIdentifier{2, 5, 29, 21} - invalidityDateExtensionOID = asn1.ObjectIdentifier{2, 5, 29, 24} -) - -type crlNumberExtension struct { - ID asn1.ObjectIdentifier - Critical bool `asn1:"optional"` - CRLNumber int -} - -// TODO: handle additional CRL Extensions -// 2.5.29.21,cRLReason -// id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 } -// -- reasonCode ::= { CRLReasonCode } - -// 2.5.29.24,invalidityDate -// id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 } -// -- InvalidityDate ::= GeneralizedTime - -// RevocationData - information on whether a certificate has been -// revoked by a specified CRL, and information on the CRL -type RevocationData struct { - CRLSignatureAlgorithm x509.SignatureAlgorithm - CRLSignatureValue []byte - Version int `asn1:"optional,default:0"` - Issuer pkix.Name - ThisUpdate time.Time - NextUpdate time.Time `asn1:"optional"` - CRLExtensions ListExtensionData - UnknownCRLExtensions []pkix.Extension `asn1:"tag:0,optional,explicit"` - UnknownCriticalCRLExtensions []pkix.Extension `asn1:"tag:0,optional,explicit"` - IsRevoked bool - RevocationTime time.Time - CertificateEntryExtensions RevokedCertExtensionData - RawCertificateEntryExtensions []pkix.Extension `asn1:"optional"` -} - -// ListExtensionData - Data from optional, non-critical pkix.CertificateList extensions -type ListExtensionData struct { - CRLNumber int - AuthKeyID x509.SubjAuthKeyId `json:"authority_key_id,omitempty"` -} - -// RevokedCertExtensionData - Data from optional, non-critical pkix.RevokedCertificate extensions -type RevokedCertExtensionData struct { - Reason *RevocationReasonCode - invalidityDate time.Time -} - -func gatherListExtensionInfo(certList *pkix.CertificateList, ret *RevocationData) { - for _, extension := range certList.TBSCertList.Extensions { - if extension.Id.Equal(crlNumberExtensionOID) { - var ext crlNumberExtension - asn1.Unmarshal(extension.Value, &ext.CRLNumber) - ret.CRLExtensions.CRLNumber = ext.CRLNumber - } else if extension.Critical { - ret.UnknownCriticalCRLExtensions = append(ret.UnknownCriticalCRLExtensions, extension) - } else { - ret.UnknownCRLExtensions = append(ret.UnknownCRLExtensions, extension) - } - } -} - -// CheckCRLForCert - parses through a given CRL and to see if a given certificate -// is present, and returns data on the revocation and CRL in general -func CheckCRLForCert(certList *pkix.CertificateList, cert *x509.Certificate, cache map[string]*pkix.RevokedCertificate) (*RevocationData, error) { - ret := &RevocationData{ - CRLSignatureAlgorithm: x509.GetSignatureAlgorithmFromAI(certList.SignatureAlgorithm), - CRLSignatureValue: certList.SignatureValue.Bytes, - Version: certList.TBSCertList.Version, - ThisUpdate: certList.TBSCertList.ThisUpdate, - NextUpdate: certList.TBSCertList.NextUpdate, - IsRevoked: false, - } - ret.Issuer.FillFromRDNSequence(&certList.TBSCertList.Issuer) - - gatherListExtensionInfo(certList, ret) - - if cache != nil { - if val, ok := cache[cert.SerialNumber.String()]; ok { - ret.IsRevoked = true - ret.RevocationTime = val.RevocationTime - } - return ret, nil - } - - // else no cache was given, must linear search through - revokedCerts := certList.TBSCertList.RevokedCertificates - for i := range revokedCerts { - if revokedCerts[i].SerialNumber.Cmp(cert.SerialNumber) == 0 { - ret.IsRevoked = true - ret.RevocationTime = revokedCerts[i].RevocationTime - break - } - } - return ret, nil -} diff --git a/crypto/x509/revocation/crl/crl_test.go b/crypto/x509/revocation/crl/crl_test.go deleted file mode 100644 index b0c6039d263..00000000000 --- a/crypto/x509/revocation/crl/crl_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package crl_test - -import ( - "io" - "os" - "testing" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/crypto/x509/revocation/crl" -) - -const example_cert = ` ------BEGIN CERTIFICATE----- -MIIFLzCCBBegAwIBAgIQQFFpI7/egSZZtXZGsGlOJDANBgkqhkiG9w0BAQsFADB+ -MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd -BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj -IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE2MDgwMTAwMDAwMFoX -DTE4MDkzMDIzNTk1OVowgZIxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9p -czEQMA4GA1UEBwwHT2dsZXNieTEqMCgGA1UECgwhSWxsaW5vaXMgVmFsbGV5IENv -bW11bml0eSBDb2xsZWdlMRIwEAYDVQQLDAlCb29rc3RvcmUxHjAcBgNVBAMMFXd3 -dy5pdmNjYm9va3N0b3JlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMUOWilh91JLixiaYMj9rtJPzAQh68Q/IrcmHZHH7NBeN4bBb2UwQTOpXjTw -boCdgVm1Ta4OOblk2kBLlZTHp0Zp6BYEZK3uAjmxe2NipvitFA0FkBuWJfC1Xj+S -nBjDwUqSskC92z6JnDzt3d2gZazmK69MdiuqYI2scgeCcGf2DeWvBnR+WHJ76O5d -rNcx/GvndIhqMBHd6b9yNyTsX8ZfxzCaWmIU36Z3GciWzaYV80hkBFDC4/TJ9dsS -2IW7POl8wHdzdBcHvOVYAVQKPpVRc1DQIIWQNalHHbKZ/J2SgM5G2v7ODv3eWxRM -uyzoSuBRksG+fxSUrz/QXfo9w3kCAwEAAaOCAZIwggGOMDMGA1UdEQQsMCqCFXd3 -dy5pdmNjYm9va3N0b3JlLmNvbYIRaXZjY2Jvb2tzdG9yZS5jb20wCQYDVR0TBAIw -ADAOBgNVHQ8BAf8EBAMCBaAwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NzLnN5 -bWNiLmNvbS9zcy5jcmwwYQYDVR0gBFowWDBWBgZngQwBAgIwTDAjBggrBgEFBQcC -ARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGQwXaHR0cHM6 -Ly9kLnN5bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC -MB8GA1UdIwQYMBaAFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMFcGCCsGAQUFBwEBBEsw -STAfBggrBgEFBQcwAYYTaHR0cDovL3NzLnN5bWNkLmNvbTAmBggrBgEFBQcwAoYa -aHR0cDovL3NzLnN5bWNiLmNvbS9zcy5jcnQwEwYKKwYBBAHWeQIEAwEB/wQCBQAw -DQYJKoZIhvcNAQELBQADggEBAJAl0wcd/QnYXtJc2PGkVMDneU29BYaSBZG4xaAU -8uWTspP+Nfb7UAcoT71oHpN8UFAiXQf1+bAorfofd1qQcZjUc5vAg04hK/r0ogI1 -rLvBJe4/jW3BzFbpgNFl+I2cnY5eRz5ZL1EeKwDxpqK1gSLlTtqwkaiIynqdBCfX -lqDnqLozsE/vn2hNh3zc1zxj1Io36ALADtJOhw/HGlrabYlHh1o7XCm2/9y0scKH -rsfxMSV9FBVsbBJutTs3nfTGiMR4XISOueetlln3/2ZlNDfGXiXdy9D5/PnxbOqL -gGR2BKlwVlQR5rRkASVSMuNFHz2QN3Ddk0SQfR/aWGwiofU= ------END CERTIFICATE-----` - -const revoked_cert = ` ------BEGIN CERTIFICATE----- -MIIH3zCCBsegAwIBAgIQAJ556Y+Dc6wJawjKBbU2XDANBgkqhkiG9w0BAQsFADB+ -MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd -BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj -IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE2MDgwNjAwMDAwMFoX -DTE5MDgwNzIzNTk1OVowazELMAkGA1UEBhMCR0IxGTAXBgNVBAgMEE5vcnRoIEh1 -bWJlcnNpZGUxDzANBgNVBAcMBkhlc3NsZTEZMBcGA1UECgwQdGhlIGFjZXkgbGlt -aXRlZDEVMBMGA1UEAwwMdGhlLWFjZXkuY29tMIICIjANBgkqhkiG9w0BAQEFAAOC -Ag8AMIICCgKCAgEAtTGBRlKPAHeTy2m39IlaoQHEzSw7hcVp7hX9H76Ajgb9x8vs -GW/ExkY3FNEiyKfy55MyYUgFZRxDz6nrdqixxI+ICVkySm3jv3ib0LGkVuYdYSNe -mvIY4l14y04gvozwMN2bO9kMYLcM7kp2JvN8vhOSbnSQ8MOyh0Iyl/F0r+5ijEWi -bCG//IBPDvV0lx+54KUikMEciM6y6Xt1g6yWYlGQweTcfcJSZfd7mQiAcXvdYFhC -mPRTFjdOGhFa8xW9SzHoaIscaulE21YcNdwxGp/0M9i48sFETvAWveYB8305YLmn -VL7EWisTRRUU/A+eFlT785TmCEuGc9siIkRc+vaWDWYWdIImRErjmqvugxBVPIlm -uEs477i2VWKwSnLNiauBf9392mQlTlVa4IGo7oWQLqqVWUX8WZ7punCEEoPT8cuW -rNiO6XHk11jWzxXlOKbi2fOSgTMN1fXHYFTIyzFL6zkoVhuMsnfR+XiswLTrz0g5 -WAe0JbrsqrS9G7pTjJIrF9Cys/bwteh1qVIOb7x8cZkZW/ujIp7DQlQjnEDymxrY -TMnOFrqrwxqvErYZJ83mbLhpGk7i3WQ3haEr+WRpeQE4Kd6LyCf9z3yxaQBlAz2r -0O6QJZBUrafq8ROuitnIvQD4VbAUtO7w5m15ScR9DxIF5Mnz/gYBxMoPCekCAwEA -AaOCA2owggNmMCkGA1UdEQQiMCCCDHRoZS1hY2V5LmNvbYIQd3d3LnRoZS1hY2V5 -LmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDArBgNVHR8EJDAiMCCgHqAc -hhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNybDBhBgNVHSAEWjBYMFYGBmeBDAEC -AjBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEF -BQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAdBgNVHSUEFjAUBggrBgEF -BQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAUX2DPYZBV34RDFIpgKrL1evRDGO8w -VwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc3Muc3ltY2QuY29t -MCYGCCsGAQUFBzAChhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNydDCCAfMGCisG -AQQB1nkCBAIEggHjBIIB3wHdAHUA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHE -zbbsvswAAAFWX530QAAABAMARjBEAiAX/oo2CAfss96T45QcePOF5GOrfHMetyrj -VleQwa6P5AIgT344qwVLkVOU5zSKEhIfGnGv4nw0bUX+FByZOagTWRsAdQCkuQmQ -tBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVZfnfRcAAAEAwBGMEQCIHCd -6zOpWxzEim6V+dGPpJ/x1jvFedY2Pd4LgyFzT1nBAiAihweZTHgqX799FjCSV5+v -TXgGHNBMOs54WnaWSB1XyQB2AGj2mPgfZIK+OozuuSgdTPxxUV1nk9RE0QpnrLtP -T/vEAAABVl+d9zYAAAQDAEcwRQIhAKAiY1lHyutn3j4RnpK2DN0ryeDJXo8a2wjU -7+OMJavDAiAu7uDUTNP7/g8fnk/nl8lnqzCFI4ufSH+OSkKW8jV28QB1AO5Lvbd1 -zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABVl+d9IYAAAQDAEYwRAIgNbca -rDjgoBfcHWr340TSIJpGxECRAwCN8PGVoqbwdjkCIEN3XXSNlI9ylQhOX032gSNp -K7nRKzCftpzm65BrCxTcMA0GCSqGSIb3DQEBCwUAA4IBAQA4X7vWBeHWhJegov41 -D5TmdPhn1uVGXH++fnLvfLFuYZCGnVCXsoN2JmnWHbfseU/wjPSDei0enGrz4fKu -4pBhaBrHcIn0/g8IGvPSoJyz6wreM5kQ6sGTJ3/JJOSPL47Z3592B8uEkfCxFmDY -TsyQxWRjCU+ijKfvR2mmrOrVAlAkXXkVwG/m9XFq/fPMgnrndrFCVp2x5XCZLOrj -coBlQ+8ShwqvpXimsHANhuqpWhoecnd/JVvmnLluiGKFtTIBqM+HUp2XD2uZIzrC -t5lh3BltMBRx79e3v7yK6db4CDNdRGLnN58+WpIlsmuPcb0SNoiaiAVtg4lLULwS -g7YS ------END CERTIFICATE-----` - -const issuer_cert = ` ------BEGIN CERTIFICATE----- -MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw -CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV -BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs -YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb -A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW -9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu -s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T -L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK -Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBYzCCAV8wEgYDVR0T -AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu -Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wawYDVR0gBGQwYjBgBgpg -hkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20v -Y3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMCkG -A1UdEQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0xLTUzNDAdBgNVHQ4E -FgQUX2DPYZBV34RDFIpgKrL1evRDGO8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnz -Qzn6Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBAF6UVkndji1l9cE2UbYD49qecxny -H1mrWH5sJgUs+oHXXCMXIiw3k/eG7IXmsKP9H+IyqEVv4dn7ua/ScKAyQmW/hP4W -Ko8/xabWo5N9Q+l0IZE1KPRj6S7t9/Vcf0uatSDpCr3gRRAMFJSaXaXjS5HoJJtG -QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t -TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY -Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc= ------END CERTIFICATE-----` - -const test_crl_location = `./test_crl` - -func parseCertPEM(t *testing.T) (cert *x509.Certificate, revoked *x509.Certificate, issuer *x509.Certificate) { - certPool := x509.NewCertPool() - ok := certPool.AppendCertsFromPEM([]byte(example_cert)) - if !ok { - t.Fail() - } - ok = certPool.AppendCertsFromPEM([]byte(issuer_cert)) - if !ok { - t.Fail() - } - ok = certPool.AppendCertsFromPEM([]byte(revoked_cert)) - if !ok { - t.Fail() - } - cert = certPool.Certificates()[0] - issuer = certPool.Certificates()[1] - revoked = certPool.Certificates()[2] - return -} - -func testCerts(t *testing.T, certList *pkix.CertificateList, cache map[string]*pkix.RevokedCertificate) { - cert, revoked, _ := parseCertPEM(t) - // check non-revoked cert - status, err := crl.CheckCRLForCert(certList, cert, cache) - if err != nil { - t.Error(err.Error()) - } - if status.IsRevoked != false { - t.Fail() - } - // check revoked cert - status, err = crl.CheckCRLForCert(certList, revoked, cache) - if err != nil { - t.Error(err.Error()) - } - if status.IsRevoked != true { - t.Fail() - } -} - -func loadCRL(t *testing.T) (certList *pkix.CertificateList) { - crlFile, err := os.Open(test_crl_location) - if err != nil { - t.Error(err.Error()) - } - crlBytes, err := io.ReadAll(crlFile) - if err != nil { - t.Error(err.Error()) - } - crlFile.Close() - certList, err = x509.ParseCRL(crlBytes) - if err != nil { - t.Error(err.Error()) - } - return -} - -func TestCRLParse(t *testing.T) { - certList := loadCRL(t) - testCerts(t, certList, nil) -} - -func TestCRLParseWithCache(t *testing.T) { - certList := loadCRL(t) - cache := make(map[string]*pkix.RevokedCertificate) - for _, cert := range certList.TBSCertList.RevokedCertificates { - cache[cert.SerialNumber.String()] = &cert - } - testCerts(t, certList, cache) -} - -func TestReasonCode(t *testing.T) { - var status crl.RevocationReasonCode = 0 - if status.String() != "unspecified" { - t.Fail() - } - statusJson, err := status.MarshalJSON() - if err != nil { - t.Error(err.Error()) - } - // test good unmarshal - err = status.UnmarshalJSON(statusJson) - if err != nil { - t.Error(err.Error()) - } - // test bad unmarshal - err = status.UnmarshalJSON(statusJson[0:5]) // this should fail! - if err == nil { - t.Fail() - } -} diff --git a/crypto/x509/revocation/crl/test_crl b/crypto/x509/revocation/crl/test_crl deleted file mode 100644 index 67eedf91bd0..00000000000 Binary files a/crypto/x509/revocation/crl/test_crl and /dev/null differ diff --git a/crypto/x509/revocation/google/google.go b/crypto/x509/revocation/google/google.go deleted file mode 100644 index 3431d516386..00000000000 --- a/crypto/x509/revocation/google/google.go +++ /dev/null @@ -1,361 +0,0 @@ -package google - -import ( - "archive/zip" - "bytes" - "encoding/binary" - "encoding/hex" - "encoding/json" - "encoding/xml" - "errors" - "io" - "math/big" - "net/http" - "net/url" - - "github.com/runZeroInc/excrypto/crypto/x509" -) - -// Provider specifies CRLSet provider interface -type Provider interface { - FetchAndParse() (*CRLSet, error) -} - -// CRLSet - data structure for storing CRLSet data, used by methods below -type CRLSet struct { - Version string - IssuerLists map[string]*IssuerList - Sequence int - NumParents int - BlockedSPKIs []string -} - -// IssuerList - list of revoked certificate entries for a given issuer -type IssuerList struct { - SPKIHash string // SHA256 of Issuer SPKI - Entries []*Entry -} - -// Entry - entry for a single certificate -type Entry struct { - SerialNumber *big.Int -} - -// defaultProvider provides default Provider -type defaultProvider struct { - requestURL string -} - -// NewProvider returns default Provider -func NewProvider(requestURL string) Provider { - return &defaultProvider{ - requestURL: requestURL, - } -} - -// FetchAndParse - fetch from distribution point, parse to CRLSet struct as defined above -func FetchAndParse() (*CRLSet, error) { - return NewProvider(VersionRequestURL()).FetchAndParse() -} - -// FetchAndParse - fetch from distribution point, parse to CRLSet struct as defined above -func (p *defaultProvider) FetchAndParse() (*CRLSet, error) { - crlSetReader, version, err := Fetch(p.requestURL) - if err != nil { - return nil, err - } - return Parse(crlSetReader, version) -} - -// Check - Given a parsed CRLSet, check if a given cert is present -func (crlSet *CRLSet) Check(cert *x509.Certificate, issuerSPKIHash string) *Entry { - // check for BlockedSPKIs first - for _, spki := range crlSet.BlockedSPKIs { - if issuerSPKIHash == spki { - return &Entry{ - SerialNumber: cert.SerialNumber, - } - } - } - - issuersRevokedCerts := crlSet.IssuerLists[issuerSPKIHash] - if issuersRevokedCerts == nil { // no entries for this issuer - return nil - } - for _, entry := range issuersRevokedCerts.Entries { - if entry.SerialNumber.Cmp(cert.SerialNumber) == 0 { - return entry - } // cert not found if for loop completes - } - return nil -} - -// Implementation details below - includes home-baked parsing of Google Update data, -// originally found at https://github.com/agl/crlset-tools - -// Types for Google Update Data - used as wrapper for CRLSet -type update struct { - XMLName xml.Name `xml:"gupdate"` - Apps []updateApp `xml:"app"` -} - -type updateApp struct { - AppID string `xml:"appid,attr"` - UpdateCheck updateCheck -} - -type updateCheck struct { - XMLName xml.Name `xml:"updatecheck"` - URL string `xml:"codebase,attr"` - Version string `xml:"version,attr"` -} - -// crlSetAppID is the hex(ish) encoded public key hash of the key that signs -// the CRL sets. -const crlSetAppID = "hfnkpimlhhgieaddgfemjhofmfblmnib" - -// VersionRequestURL returns a URL from which the current CRLSet version -// information can be fetched. -func VersionRequestURL() string { - args := url.Values(make(map[string][]string)) - args.Add("x", "id="+crlSetAppID+"&v=&uc"+"&acceptformat=crx3") - - return (&url.URL{ - Scheme: "https", - Host: "clients2.google.com", - Path: "/service/update2/crx", - RawQuery: args.Encode(), - }).String() -} - -// CRXHeader reflects the binary header of a CRX file. -type CRXHeader struct { - Magic [4]byte - Version uint32 - HeaderLen uint32 -} - -// ZipReader is a small wrapper around a []byte which implements ReadAt. -type ZipReader []byte - -// ReadAt - Implementation of ReadAt for ZipReader App -func (z ZipReader) ReadAt(p []byte, pos int64) (int, error) { - if int(pos) < 0 { - return 0, nil - } - return copy(p, []byte(z)[int(pos):]), nil -} - -// Fetch returns reader to be passed to Parse -func Fetch(url string) ([]byte, string, error) { - resp, err := http.Get(url) - if err != nil { - err = errors.New("Failed to get current version: " + err.Error()) - return nil, "", err - } - - var reply update - bodyBytes, err := io.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - err = errors.New("Failed to read version reply: " + err.Error()) - return nil, "", err - } - if err = xml.Unmarshal(bodyBytes, &reply); err != nil { - err = errors.New("Failed to parse version reply: " + err.Error()) - return nil, "", err - } - - var crxURL, version string - for _, app := range reply.Apps { - if app.AppID == crlSetAppID { - crxURL = app.UpdateCheck.URL - version = app.UpdateCheck.Version - break - } - } - - if len(crxURL) == 0 { - err = errors.New("Failed to parse Omaha response") - return nil, version, err - } - - resp, err = http.Get(crxURL) - if err != nil { - err = errors.New("Failed to get CRX: " + err.Error()) - return nil, version, err - } - defer resp.Body.Close() - - // zip needs to seek around, so we read the whole reply into memory. - crxBytes, err := io.ReadAll(resp.Body) - if err != nil { - err = errors.New("Failed to download CRX: " + err.Error()) - return nil, version, err - } - crx := bytes.NewBuffer(crxBytes) - - var header CRXHeader - if err = binary.Read(crx, binary.LittleEndian, &header); err != nil { - err = errors.New("Failed to parse CRX header: " + err.Error()) - return nil, version, err - } - - if !bytes.Equal(header.Magic[:], []byte("Cr24")) || int(header.HeaderLen) < 0 { - err = errors.New("Downloaded file doesn't look like a CRX") - return nil, version, err - } - - protoHeader := crx.Next(int(header.HeaderLen)) - if len(protoHeader) != int(header.HeaderLen) { - err = errors.New("Downloaded file doesn't look like a CRX") - return nil, version, err - } - - zipBytes := crx.Bytes() - zipReader := ZipReader(crx.Bytes()) - - z, err := zip.NewReader(zipReader, int64(len(zipBytes))) - if err != nil { - err = errors.New("Failed to parse ZIP file: " + err.Error()) - return nil, version, err - } - - var crlFile *zip.File - for _, file := range z.File { - if file.Name == "crl-set" { - crlFile = file - break - } - } - - if crlFile == nil { - err = errors.New("Downloaded CRX didn't contain a CRLSet") - return nil, version, err - } - - crlSetReader, err := crlFile.Open() - if err != nil { - err = errors.New("Failed to open crl-set in ZIP: " + err.Error()) - return nil, version, err - } - - raw, err := io.ReadAll(crlSetReader) - if err != nil { - return nil, version, err - } - - return raw, version, nil -} - -// CRLSetHeader is used to parse the JSON header found in CRLSet files. -type CRLSetHeader struct { - Sequence int - NumParents int - BlockedSPKIs []string -} - -// RawEntry - structure for a raw CRLSet entry -type RawEntry struct { - SPKIHash [32]byte // SHA256 of Issuer SPKI - NumSerials uint32 - Serials []RawCRLSetSerial -} - -// RawCRLSetSerial - structure of certificate serial number in a raw CRLSet entry -type RawCRLSetSerial struct { - Len uint8 - SerialBytes []byte -} - -// Parse - given a reader for a raw byte stream for a CRLSet, -// parse the file into a usable CRLSet struct instance. -// DUE TO THE DIFFICULTY OF RETRIEVING A CRLSET, IT IS HIGHLY RECOMMENDED -// TO JUST USE THE FetchAndParseCRLSet FUNCTION PROVIDED ABOVE -func Parse(in []byte, version string) (*CRLSet, error) { - header, remainingBytes, err := getHeader(in) - if err != nil { - return nil, err - } - - rest := bytes.NewReader(remainingBytes) - - crlSet := CRLSet{} - crlSet.IssuerLists = map[string]*IssuerList{} - crlSet.Sequence = header.Sequence - crlSet.Version = version - crlSet.NumParents = header.NumParents - crlSet.BlockedSPKIs = header.BlockedSPKIs - - for rest.Len() > 0 { - rawEntry := RawEntry{} - issuerList := IssuerList{} - err := binary.Read(rest, binary.LittleEndian, &rawEntry.SPKIHash) - if err != nil { - return nil, err - } - - issuerList.SPKIHash = hex.EncodeToString(rawEntry.SPKIHash[:]) - crlSet.IssuerLists[issuerList.SPKIHash] = &issuerList - - err = binary.Read(rest, binary.LittleEndian, &rawEntry.NumSerials) - if err != nil { - return nil, err - } - - for i := uint32(0); i < rawEntry.NumSerials; i++ { - if rest.Len() < 1 { - err = errors.New("CRLSet truncated at serial length") - return nil, err - } - serial := RawCRLSetSerial{} - entry := Entry{} - issuerList.Entries = append(issuerList.Entries, &entry) - err = binary.Read(rest, binary.LittleEndian, &serial.Len) - if err != nil { - return nil, err - } - - if rest.Len() < int(serial.Len) { - err = errors.New("CRLSet truncated at serial") - return nil, err - } - - serialBytes := make([]byte, serial.Len) - err = binary.Read(rest, binary.LittleEndian, &serialBytes) - if err != nil { - return nil, err - } - serialNumber := new(big.Int) - serialNumber.SetBytes(serialBytes) - entry.SerialNumber = serialNumber - } - } - - return &crlSet, nil -} - -// internal method for parsing header when parsing a CRLSet -func getHeader(c []byte) (header CRLSetHeader, rest []byte, err error) { - if len(c) < 2 { - err = errors.New("CRLSet truncated at header length") - return - } - - headerLen := int(binary.LittleEndian.Uint16(c[0:])) - c = c[2:] - - if len(c) < headerLen { - err = errors.New("CRLSet truncated at header") - return - } - headerBytes := c[:headerLen] - c = c[headerLen:] - - if err = json.Unmarshal(headerBytes, &header); err != nil { - err = errors.New("Failed to parse header: " + err.Error()) - return - } - - return header, c, nil -} diff --git a/crypto/x509/revocation/google/google_test.go b/crypto/x509/revocation/google/google_test.go deleted file mode 100644 index 0fd27f6860b..00000000000 --- a/crypto/x509/revocation/google/google_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package google_test - -import ( - "io" - "net/http" - "net/http/httptest" - "os" - "strings" - "testing" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/revocation/google" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// obtained from https://firefox.settings.services.mozilla.com/v1/buckets/blocklists/collections/certificates/records -const ( - crlset_location = `./testdata/test_crlset` - VERSION = "4619" -) - -const revoked_intermediate = ` ------BEGIN CERTIFICATE----- -MIIHVTCCBT2gAwIBAgIIEOqAPvgqxt8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE -BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xMzAyMjAxMDAzMTdaFw0zMDEy -MzEwNTA1NDJaMIGNMQswCQYDVQQGEwJFUzEeMBwGA1UEChMVRmlybWFwcm9mZXNp -b25hbCBTLkEuMRowGAYDVQQLExFTZWN1cml0eSBTZXJ2aWNlczESMBAGA1UEBRMJ -QTYyNjM0MDY4MS4wLAYDVQQDEyVBQyBGaXJtYXByb2Zlc2lvbmFsIC0gSU5GUkFF -U1RSVUNUVVJBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuqX7V9RP -HmZ/SpGlhXSfREEtOiiRS8SdJC1QuOB2EYLiFEeL2QFZHIRP4HBm+CbLZ7ts+GLD -5XOGWa84Q9BgRI2HXF4E9PeCQh+ejtnnpDRQlx/cIkX5zt750xXfjArifVS4IUHR -fiyfZmNuyn3qqB5O/nz1K/YelKSZtbjc00qlwXU4sfrZRFJgm0PD6oxJqLoU8VVE -jBzdbVWsG9KEc91gG0u5UJZyLWGJP2f7I/zrki2WOf9SPfrA01viYw2PSe/81Z7O -tADKy076N6Z8ky4HaS1aNsqxx/LTylUh+9O0ccGKSQSpO87LFbrKNilGvIRQYzrj -ItUawGsF0KuUEwIDAQABo4IC8jCCAu4wdAYIKwYBBQUHAQEEaDBmMDYGCCsGAQUF -BzAChipodHRwOi8vY3JsLmZpcm1hcHJvZmVzaW9uYWwuY29tL2Nhcm9vdC5jcnQw -LAYIKwYBBQUHMAGGIGh0dHA6Ly9vY3NwLmZpcm1hcHJvZmVzaW9uYWwuY29tMB0G -A1UdDgQWBBRiFau1swh5pYf+gNki8I78jxH9eTASBgNVHRMBAf8ECDAGAQH/AgEA -MB8GA1UdIwQYMBaAFGXN66s1HgA+ftV0wBy0c0cOGmQvMIIB0gYDVR0gBIIByTCC -AcUwggHBBgorBgEEAeZ5CgoBMIIBsTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5m -aXJtYXByb2Zlc2lvbmFsLmNvbS9jcHMwggF8BggrBgEFBQcCAjCCAW4eggFqAEMA -ZQByAHQAaQBmAGkAYwBhAGQAbwAgAGQAZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAA -ZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAuACAAQwBvAG4AcwB1AGwA -dABlACAAbABhAHMAIABjAG8AbgBkAGkAYwBpAG8AbgBlAHMAIABkAGUAIAB1AHMA -bwAgAGUAbgAgAC8AIABDAGUAcgB0AGkAZgBpAGMAYQB0AGkAbwBuACAAQQB1AHQA -aABvAHIAaQB0AHkAIABjAGUAcgB0AGkAZgBpAGMAYQB0AGUALgAgAFMAZQBlACAA -dABlAHIAbQBzACAAYQBuAGQAIABjAG8AbgBkAGkAdABpAG8AbgBzACAAYQB0ACAA -IABoAHQAdABwADoALwAvAHcAdwB3AC4AZgBpAHIAbQBhAHAAcgBvAGYAZQBzAGkA -bwBuAGEAbAAuAGMAbwBtAC8AYwBwAHMwPAYDVR0fBDUwMzAxoC+gLYYraHR0cHM6 -Ly9jcmwuZmlybWFwcm9mZXNpb25hbC5jb20vZnByb290LmNybDAOBgNVHQ8BAf8E -BAMCAQYwDQYJKoZIhvcNAQEFBQADggIBAGRD/ej1VKQGfWiBwL8I6plyFfvplmwO -+N7EpzUifUgn2sDHiL2L2V5nQdN2lLL5tI83JimPKybrHbv9EwSGPsTOgY+8HWCA -iaq9dLKVHRK93/FvI+Wj63X6pvx5YDiT2Kq7RuXQFx8AG+acwMa7WHaeravzAiSd -pak4qW5KlZ54RxiTNtFGwuEGpHc7wakdWSH3hUYfXNLz8JC9DmNqG8ZxAf3Z8AJq -vIeH4NRPkZ6//QG5JzPowb8eNG2v84ZYQStIAsHa0sVdq9o/zK9x2isv4Y+5GAw4 -bnfq14G23Zh1oFS2T6la7W+AR3OGhP8Y6Xt+TFhn10yfE4TrFGNr20akj2TddsMj -SAatoB2gE3f7wTFsrXdJn0aJ/18KdlqV0NNuHrs/ZOIhnt7qswZVQfeQHHUQpwOp -CJrveDbSDZz3Kmo0afJtkcyAnZEPdFdyq8YgqfSqyJs6PJuemsj2ipai0gWO/3f8 -EcApsll70fMRVXfOObBcO+hEO1tN0etNLlT5mlulpbMpkJ6hRgcHmVqogw1YJhmL -/E03f6Lw8aaCT9yDunE66bFZ/gwNky0V9PvCQni4GmGSKqcM2hFPux6FIWOOokBE -bicOgqIPCJodWamv++aE/6VKV6Th5gyYBJQ5Pjb6BRxpXtCVAVrev9ZIFcmYn6LX -wp6ggHtX2lGF ------END CERTIFICATE----- -` - -const PARENT_SPKI_HASH = `3b0d73b4be4a854adc3e51d7ef9fa48aefbb2cdd824d67bdc7d7d09a2abc2d43` - -func parseCertPEM(t *testing.T) (revoked *x509.Certificate) { - certPool := x509.NewCertPool() - ok := certPool.AppendCertsFromPEM([]byte(revoked_intermediate)) - if !ok { - t.Fail() - } - revoked = certPool.Certificates()[0] - return -} - -func loadRevokedList(t *testing.T) (crlset *google.CRLSet) { - crlSetFile, err := os.Open(crlset_location) - if err != nil { - t.Error(err.Error()) - } - defer crlSetFile.Close() - - crlSetBytes, err := io.ReadAll(crlSetFile) - if err != nil { - t.Error(err.Error()) - } - - crlset, err = google.Parse(crlSetBytes, VERSION) - if err != nil { - t.Error(err.Error()) - } - return -} - -// Parses a static, stored version of an issued CRLSet - to prevent -// unexpected breakage with tests, use this instead of a live -// fetch when possible -func TestParse(t *testing.T) { - loadRevokedList(t) -} - -func TestParse6375(t *testing.T) { - raw, err := os.ReadFile("testdata/crl-set-6375") - if err != nil { - t.Error(err.Error()) - } - - set, err := google.Parse(raw, "6375") - if err != nil { - t.Error(err.Error()) - } - if "6375" != set.Version { - t.Fail() - } -} - -// just tests that there are no major complaints when live fetching, -// don't actually use this in case google removes our testing intermediate -// cert from the revocation list -func TestFetchRemote(t *testing.T) { - list, err := google.FetchAndParse() - if list == nil || err != nil { - t.Fail() - } -} - -func TestCheck(t *testing.T) { - revoked := parseCertPEM(t) - crlset := loadRevokedList(t) - - entry := crlset.Check(revoked, PARENT_SPKI_HASH) - if entry == nil { // this should provide an entry, since cert is revoked and in the provided sst file - t.Fatalf("empty entry") - } - if entry.SerialNumber == nil { - t.Fatalf("empty serial") - } - if entry.SerialNumber.Cmp(revoked.SerialNumber) != 0 { - t.Fail() - } -} - -func TestFetch(t *testing.T) { - bytes, err := os.ReadFile("testdata/APm1SaUzZaPllaSDuZS5yng") - require.NoError(t, err) - - versionResponse := `xml version="1.0" encoding="UTF-8"?> - - - - - - ` - - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - - if r.RequestURI == "/APm1SaUzZaPllaSDuZS5yng" { - _, _ = w.Write(bytes) - } else { - _, _ = w.Write([]byte(versionResponse)) - } - }) - server := httptest.NewServer(h) - defer server.Close() - - versionResponse = strings.Replace(versionResponse, - "http://dl.google.com/APm1SaUzZaPllaSDuZS5yng", - server.URL+"/APm1SaUzZaPllaSDuZS5yng", 1) - - p := google.NewProvider(server.URL) - set, err := p.FetchAndParse() - require.NoError(t, err) - assert.Equal(t, 6376, set.Sequence) -} diff --git a/crypto/x509/revocation/google/testdata/APm1SaUzZaPllaSDuZS5yng b/crypto/x509/revocation/google/testdata/APm1SaUzZaPllaSDuZS5yng deleted file mode 100644 index 209025cf7be..00000000000 Binary files a/crypto/x509/revocation/google/testdata/APm1SaUzZaPllaSDuZS5yng and /dev/null differ diff --git a/crypto/x509/revocation/google/testdata/crl-set-6375 b/crypto/x509/revocation/google/testdata/crl-set-6375 deleted file mode 100644 index 35391b30b5b..00000000000 Binary files a/crypto/x509/revocation/google/testdata/crl-set-6375 and /dev/null differ diff --git a/crypto/x509/revocation/google/testdata/test_crlset b/crypto/x509/revocation/google/testdata/test_crlset deleted file mode 100644 index b9b955a3ba7..00000000000 Binary files a/crypto/x509/revocation/google/testdata/test_crlset and /dev/null differ diff --git a/crypto/x509/revocation/microsoft/microsoft.go b/crypto/x509/revocation/microsoft/microsoft.go deleted file mode 100644 index 36bcf64f3bf..00000000000 --- a/crypto/x509/revocation/microsoft/microsoft.go +++ /dev/null @@ -1,171 +0,0 @@ -package microsoft - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "math/big" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" -) - -// distribution point http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/disallowedcert.sst - -// DisallowedCerts - data structure for storing certificates revoked by -// Microsoft's intermediate revocation mechanism, disallowedcert.sst -type DisallowedCerts struct { - IssuerLists map[string]*IssuerList -} - -// IssuerList - List of revoked cert entries given issuer -type IssuerList struct { - Issuer pkix.Name - Entries []*Entry -} - -// Entry - Revocation Data for a single Certificate -type Entry struct { - SerialNumber *big.Int -} - -// Parse raw disallowedcert.sst and return an instance of DisallowedCerts, -// a struct for easy checking of revocation data for certs -func Parse(byteData []byte) (*DisallowedCerts, error) { - return parse(byteData) -} - -// Check - Given a parsed DisallowedCerts instance created by the Parse Func, -// check to see if a provided certificate has been revoked by this list -func Check(disallowed *DisallowedCerts, cert *x509.Certificate) *Entry { - if disallowed == nil || disallowed.IssuerLists == nil { - return nil - } - issuerStr := cert.Issuer.String() - issuersRevokedCerts := disallowed.IssuerLists[issuerStr] - if issuersRevokedCerts == nil { // no entries for this issuer - return nil - } - for _, entry := range issuersRevokedCerts.Entries { - if entry.SerialNumber.Cmp(cert.SerialNumber) == 0 { - return entry - } // cert not found if for loop completes - } - return nil -} - -// Structs and methods below are original format for disallowedcert.sst, -// used for parsing raw data from the distribution point -// Implementation details below - includes home-baked parsing Microsoft sst format - -// VBASigSerializedCertStore - The serialized digital certificate store specifies -// structures for storing a digital certificate store containing a single digital -// certificate and, optionally, a list of properties associated with the certificate. -type VBASigSerializedCertStore struct { - Version uint32 // must be 0x00000000 - Magic [4]byte // must be CERT in ascii - CertGroup CertStoreCertificateGroup - endMarkerElement EndElementMarkerEntry -} - -// CertStoreCertificateGroup - Specifies a grouping of elements in a serialized -// digital certificate store that consists of zero or more properties of a -// certificate, and the serialized certificate itself. -type CertStoreCertificateGroup struct { - elementList []SerializedPropertyEntry - certificateElement SerializedCertificateEntry -} - -// SerializedPropertyEntry - Specifies an entry in a serialized digital -// certificate store that contains data for a property associated with a -// certificate in the store. -type SerializedPropertyEntry struct { - ID uint32 // MUST be less than or equal to 0x0000FFFF and MUST NOT be the value 0x00000000 or 0x00000020 - EncodingType uint32 // MUST be the value 0x00000001, which specifies ASN.1 encoding - Length uint32 // specifies the length of the value field - Value []byte -} - -// SerializedCertificateEntry - Specifies an entry in a serialized digital -// certificate store that contains data for a property associated with a -// certificate in the store. -type SerializedCertificateEntry struct { - ID uint32 // MUST be 0x00000020 - EncodingType uint32 // MUST be the value 0x00000001, which specifies ASN.1 encoding - Length uint32 // specifies the length of the certificate field - Certificate []byte -} - -// EndElementMarkerEntry - Specifies a special entry in a serialized digital -// certificate store that marks the end of the store. -type EndElementMarkerEntry struct { - ID uint32 // MUST be 0x00000000 - Marker uint64 // MUST be 0x0000000000000000 -} - -// Parse through a binary representation of a SST file, -// construct map -func parse(byteData []byte) (*DisallowedCerts, error) { - bytesReader := bytes.NewReader(byteData) - var certStore VBASigSerializedCertStore - binary.Read(bytesReader, binary.LittleEndian, &certStore.Version) - binary.Read(bytesReader, binary.LittleEndian, &certStore.Magic) - - if !bytes.Equal(certStore.Magic[:], []byte("CERT")) || - certStore.Version != 0 { - err := errors.New("This file doesn't look like an SST") - return nil, err - } - - certs := [][]byte{} - - for { // read through element list and certificate elements - var id uint32 - binary.Read(bytesReader, binary.LittleEndian, &id) - if id == uint32(0) { // this is EndElementMarkerEntry, we have reached end of list - break - } - var format uint32 - binary.Read(bytesReader, binary.LittleEndian, &format) - var len uint32 - binary.Read(bytesReader, binary.LittleEndian, &len) - if id == uint32(32) { // this is a SerializedCertificateEntry - if format != uint32(1) { - err := errors.New("SST does not use ASN1 encoding") - return nil, err - } - certChain := make([]byte, len) - binary.Read(bytesReader, binary.LittleEndian, &certChain) - certs = append(certs, certChain) - } else { // this is a SerializedPropertyEntry, so skip it - _, _ = io.CopyN(io.Discard, bytesReader, int64(len)) // skip over value bytes - } - } - - disallowed := &DisallowedCerts{} - disallowed.IssuerLists = map[string]*IssuerList{} - - for i := range certs { - cert, err := x509.ParseCertificate(certs[i]) - if err != nil { - return nil, fmt.Errorf("failed to parse cert %d: %v", i, err) - } - entry := &Entry{ - SerialNumber: cert.SerialNumber, - } - issuerStr := cert.Issuer.String() - issuerList := disallowed.IssuerLists[issuerStr] - if issuerList != nil { // if list already exists for this issuer, append - issuerList.Entries = append(issuerList.Entries, entry) - } else { // create new list for this issuer - newList := &IssuerList{ - Issuer: cert.Issuer, - } - newList.Entries = append(newList.Entries, entry) - disallowed.IssuerLists[issuerStr] = newList - } - } - return disallowed, nil -} diff --git a/crypto/x509/revocation/microsoft/microsoft_test.go b/crypto/x509/revocation/microsoft/microsoft_test.go deleted file mode 100644 index f8090400239..00000000000 --- a/crypto/x509/revocation/microsoft/microsoft_test.go +++ /dev/null @@ -1,96 +0,0 @@ -package microsoft_test - -import ( - "io" - "os" - "testing" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/revocation/microsoft" - "github.com/runZeroInc/excrypto/internal/godebug" -) - -// obtained from http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/disallowedcert.sst -const disallowed_cert_location = `./test_disallowedcert.sst` - -const revoked_intermediate = ` ------BEGIN CERTIFICATE----- -MIIEiDCCA3CgAwIBAgIEATFpsDANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO -TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDcwNzA1MDg0MjA3WhcN -MTUwNzI3MDgzOTQ2WjBfMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy -IEIuVi4xNzA1BgNVBAMTLkRpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp -ZCBlbiBCZWRyaWp2ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc -vdKnTmoKuzuiheF/AK2+tDBomAfNoHrElM9x+Yo35FPrV3bMi+Zs/u6HVcg+uwQ5 -AKeAeKxbT370vbhUuHE7BzFJOZNUfCA7eSuPu2GQfbGs5h+QLp1FAalkLU3DL7nn -UNVOKlyrdnY3Rtd57EKZ96LspIlw3Dgrh6aqJOadkiQbvvb91C8ZF3rmMgeUVAVT -Q+lsvK9Hy7zL/b07RBKB8WtLu+20z6slTxjSzAL8o0+1QjPLWc0J3NNQ/aB2jKx+ -ZopC9q0ckvO2+xRG603XLzDgbe5bNr5EdLcgBVeFTegAGaL2DOauocBC36esgl3H -aLcY5olLmmv6znn58yynAgMBAAGjggFQMIIBTDBIBgNVHSAEQTA/MD0GBFUdIAAw -NTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5kaWdpbm90YXIubmwvY3BzL3BraW92 -ZXJoZWlkMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIGABgNVHSME -eTB3gBQLhtYPd6NosftkCcOIblwEHFfpPaFZpFcwVTELMAkGA1UEBhMCTkwxHjAc -BgNVBAoTFVN0YWF0IGRlciBOZWRlcmxhbmRlbjEmMCQGA1UEAxMdU3RhYXQgZGVy -IE5lZGVybGFuZGVuIFJvb3QgQ0GCBACYmnkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0 -cDovL2NybC5wa2lvdmVyaGVpZC5ubC9Eb21PdkxhdGVzdENSTC5jcmwwHQYDVR0O -BBYEFEwIyY128ZjHPt881y91DbF2eZfMMA0GCSqGSIb3DQEBBQUAA4IBAQAMlIca -v03jheLu19hjeQ5Q38aEW9K72fUxCho1l3TfFPoqDz7toOMI9tVOW6+mriXiRWsi -D7dUKH6S3o0UbNEc5W50BJy37zRERd/Jgx0ZH8Apad+J1T/CsFNt5U4X5HNhIxMm -cUP9TFnLw98iqiEr2b+VERqKpOKrp11Lbyn1UtHk0hWxi/7wA8+nfemZhzizDXMU -5HIs4c71rQZIZPrTKbmi2Lv01QulQERDjqC/zlqlUkxk0xcxYczopIro5Ij76eUv -BjMzm5RmZrGrUDqhCYF0U1onuabSJc/Tw6f/ltAv6uAejVLpGBwgCkegllYOQJBR -RKwa/fHuhR/3Qlpl ------END CERTIFICATE----- -` - -func parseCertPEM(t *testing.T) (revoked *x509.Certificate) { - certPool := x509.NewCertPool() - ok := certPool.AppendCertsFromPEM([]byte(revoked_intermediate)) - if !ok { - t.Fail() - } - revoked = certPool.Certificates()[0] - return -} - -func loadRevokedList(t *testing.T) (disallowed *microsoft.DisallowedCerts) { - sstFile, err := os.Open(disallowed_cert_location) - if err != nil { - t.Error(err.Error()) - } - sstBytes, err := io.ReadAll(sstFile) - if err != nil { - t.Error(err.Error()) - } - sstFile.Close() - disallowed, err = microsoft.Parse(sstBytes) - if err != nil { - t.Error(err.Error()) - } - return -} - -func TestParse(t *testing.T) { - loadRevokedList(t) -} - -func TestCheck(t *testing.T) { - godebug.SetEnv("GODEBUG", "x509negativeserial=1") - t.Cleanup(func() { godebug.SetEnv("GODEBUG", "") }) - - disallowed := loadRevokedList(t) - revoked := parseCertPEM(t) - entry := microsoft.Check(disallowed, revoked) - if entry == nil { // this should provide an entry, since cert is revoked and in the provided sst file - t.Fatalf("certificate entry is nil") - } - if entry.SerialNumber == nil { - t.Fatalf("entry serial is nil") - } - if revoked.SerialNumber == nil { - t.Fatalf("revoked serial is nil") - } - if entry.SerialNumber.Cmp(revoked.SerialNumber) != 0 { - t.Fail() - } -} diff --git a/crypto/x509/revocation/microsoft/test_disallowedcert.sst b/crypto/x509/revocation/microsoft/test_disallowedcert.sst deleted file mode 100644 index 3bc2dee4718..00000000000 Binary files a/crypto/x509/revocation/microsoft/test_disallowedcert.sst and /dev/null differ diff --git a/crypto/x509/revocation/mozilla/mozilla.go b/crypto/x509/revocation/mozilla/mozilla.go deleted file mode 100644 index 01512e59492..00000000000 --- a/crypto/x509/revocation/mozilla/mozilla.go +++ /dev/null @@ -1,285 +0,0 @@ -package mozilla - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - "net/http" - "time" - - "github.com/runZeroInc/excrypto/crypto/sha256" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/encoding/asn1" -) - -// Provider specifies OneCRL provider interface -type Provider interface { - FetchAndParse() (*OneCRL, error) -} - -const ( - // KintoRequestURL specifies a pre-populated URL where to send request - KintoRequestURL = "https://settings.prod.mozaws.net/v1/buckets/security-state-staging/collections/onecrl/records" - // OneCRLDistPoint specifies a pre-populated URL where to send request - OneCRLDistPoint = "https://firefox.settings.services.mozilla.com/v1/buckets/blocklists/collections/certificates/records" -) - -// defaultProvider provides default Provider -type defaultProvider struct { - requestURL string -} - -// NewProvider returns default Provider -func NewProvider(requestURL string) Provider { - return &defaultProvider{ - requestURL: requestURL, - } -} - -// FetchAndParse - fetch from distribution point, parse to OneCRL struct as defined above -func FetchAndParse() (*OneCRL, error) { - return NewProvider(OneCRLDistPoint).FetchAndParse() -} - -// OneCRL - data structure for storing OneCRL data, used by methods below -type OneCRL struct { - IssuerLists map[string]*IssuerList - - // Blocked provides a list of revoked entries by Subject and PubKeyHash - Blocked []*SubjectAndPublicKey -} - -// IssuerList - list of Entry for a given issuer -type IssuerList struct { - Issuer *pkix.Name - Entries []*Entry -} - -// Entry - entry for a single certificate -type Entry struct { - ID string - Schema time.Time - Details EntryDetails - Enabled bool - Issuer *pkix.Name - SerialNumber *big.Int - SubjectAndPublicKey *SubjectAndPublicKey - LastModified time.Time -} - -// SubjectAndPublicKey specifies a revocation entry by Subject and PubKeyHash -type SubjectAndPublicKey struct { - RawSubject []byte - Subject *pkix.Name - PubKeyHash []byte -} - -// EntryDetails - revocation details for a single entry -type EntryDetails struct { - Bug string `json:"bug,omitempty"` - Who string `json:"who,omitempty"` - Why string `json:"why,omitempty"` - Name string `json:"name,omitempty"` - Created *time.Time `json:"created,omitempty"` -} - -type record struct { - ID string `json:"id,omitempty"` - IssuerName string `json:"issuerName,omitempty"` - SerialNumber string `json:"serialNumber,omitempty"` - Subject string `json:"subject,omitempty"` - PubKeyHash string `json:"pubKeyHash,omitempty"` - Enabled bool `json:"enabled"` - Schema int `json:"schema"` - LastModified int `json:"last_modified"` - Details struct { - Who string `json:"who"` - Created string `json:"created"` - Bug string `json:"bug"` - Name string `json:"name"` - Why string `json:"why"` - } `json:"details"` -} - -func decodePkixName(name string) (*pkix.Name, []byte, error) { - issuerBytes, err := base64.StdEncoding.DecodeString(name) - if err != nil { - return nil, nil, err - } - var issuerRDN pkix.RDNSequence - _, err = asn1.Unmarshal(issuerBytes, &issuerRDN) - if err != nil { - return nil, nil, err - } - iss := new(pkix.Name) - iss.FillFromRDNSequence(&issuerRDN) - return iss, issuerBytes, nil -} - -// UnmarshalJSON implements the json.Unmarshaler interface -func (entry *Entry) UnmarshalJSON(b []byte) error { - aux := &record{} - if err := json.Unmarshal(b, &aux); err != nil { - return err - } - schemaSeconds := int64(aux.Schema) / 1000 - schema := time.Unix(schemaSeconds, 0) - lastModifiedSeconds := int64(aux.LastModified) / 1000 - lastModified := time.Unix(lastModifiedSeconds, 0) - - var createdAt *time.Time - if aux.Details.Created != "" { - var t time.Time - if err := t.UnmarshalJSON([]byte(aux.Details.Created)); err == nil { - createdAt = &t - } - } - - var err error - var subjectAndPublicKey *SubjectAndPublicKey - var issuer *pkix.Name - var serialNumber *big.Int - - if aux.Subject != "" && aux.PubKeyHash != "" { - subj, rawSubj, err := decodePkixName(aux.Subject) - if err != nil { - return fmt.Errorf("failed to unbase64 Subject: %w", err) - } - rawPubKey, err := base64.StdEncoding.DecodeString(aux.PubKeyHash) - if err != nil { - return fmt.Errorf("failed to unbase64 Subject: %w", err) - } - - subjectAndPublicKey = &SubjectAndPublicKey{ - Subject: subj, - RawSubject: rawSubj, - PubKeyHash: rawPubKey, - } - } else { - serialNumberBytes, _ := base64.StdEncoding.DecodeString(aux.SerialNumber) - serialNumber = new(big.Int).SetBytes(serialNumberBytes) - issuer, _, err = decodePkixName(aux.IssuerName) - if err != nil { - return fmt.Errorf("failed to unbase64 IssuerName: %w", err) - } - } - - *entry = Entry{ - ID: aux.ID, - Schema: schema, - Details: EntryDetails{ - Created: createdAt, - Who: aux.Details.Who, - Bug: aux.Details.Bug, - Name: aux.Details.Name, - Why: aux.Details.Why, - }, - Enabled: aux.Enabled, - Issuer: issuer, - SerialNumber: serialNumber, - SubjectAndPublicKey: subjectAndPublicKey, - LastModified: lastModified, - } - return nil -} - -// FindIssuer - given an issuer pkix.name, find its corresponding IssuerList -func (c *OneCRL) FindIssuer(issuer *pkix.Name) *IssuerList { - issuerStr := issuer.String() - return c.IssuerLists[issuerStr] -} - -// FetchAndParse - fetch from distribution point, parse to OneCRL struct as defined above -func (p *defaultProvider) FetchAndParse() (*OneCRL, error) { - raw, err := fetch(p.requestURL) - if err != nil { - return nil, err - } - return Parse(raw) -} - -func fetch(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, fmt.Errorf("Failed to get current OneCRL: %w", err) - } - - bodyBytes, err := io.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return nil, fmt.Errorf("Failed to read OneCRL response: %w", err) - } - return bodyBytes, nil -} - -// Parse - given raw bytes of OneCRL, parse and create OneCRL Object -func Parse(raw []byte) (*OneCRL, error) { - rawOneCRL := struct { - Data []Entry `json:"data"` - }{} - if err := json.Unmarshal(raw, &rawOneCRL); err != nil { - return nil, errors.New("Could not parse OneCRL: " + err.Error()) - } - oneCRL := &OneCRL{ - IssuerLists: make(map[string]*IssuerList), - Blocked: make([]*SubjectAndPublicKey, 0), - } - for i := range rawOneCRL.Data { - entry := &(rawOneCRL.Data[i]) - - if entry.SubjectAndPublicKey != nil { - oneCRL.Blocked = append(oneCRL.Blocked, entry.SubjectAndPublicKey) - continue - } - - issuerList := oneCRL.FindIssuer(entry.Issuer) - if issuerList != nil { // if list already exists for this issuer, append - issuerList.Entries = append(issuerList.Entries, entry) - } else { // create new list for this issuer - newList := &IssuerList{ - Issuer: entry.Issuer, - } - newList.Entries = append(newList.Entries, entry) - oneCRL.IssuerLists[entry.Issuer.String()] = newList - } - } - return oneCRL, nil -} - -// Check - Given a parsed OneCRL, check if a given cert is present -func (c *OneCRL) Check(cert *x509.Certificate) *Entry { - // check for BlockedSPKIs first - for _, blocked := range c.Blocked { - if bytes.Equal(blocked.RawSubject, cert.RawSubject) { - pubKeyData, _ := x509.MarshalPKIXPublicKey(cert.PublicKey) - hash := sha256.Sum256(pubKeyData) - if bytes.Equal(blocked.PubKeyHash, hash[:]) { - return &Entry{ - SubjectAndPublicKey: &SubjectAndPublicKey{ - RawSubject: cert.RawSubject, - Subject: &cert.Subject, - PubKeyHash: hash[:], - }, - } - } - } - } - - issuersRevokedCerts := c.FindIssuer(&cert.Issuer) - if issuersRevokedCerts == nil { // no entries for this issuer - return nil - } - for _, entry := range issuersRevokedCerts.Entries { - if entry.SerialNumber.Cmp(cert.SerialNumber) == 0 { - return entry - } // cert not found if for loop completes - } - - return nil -} diff --git a/crypto/x509/revocation/mozilla/mozilla_test.go b/crypto/x509/revocation/mozilla/mozilla_test.go deleted file mode 100644 index 50e64ad9228..00000000000 --- a/crypto/x509/revocation/mozilla/mozilla_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package mozilla_test - -import ( - "io" - "net/http" - "net/http/httptest" - "os" - "testing" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/revocation/mozilla" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// obtained from https://firefox.settings.services.mozilla.com/v1/buckets/blocklists/collections/certificates/records -const onecrl_location = `./testdata/test_onecrl.json` - -const revoked_intermediate = ` ------BEGIN CERTIFICATE----- -MIIEiDCCA3CgAwIBAgIEATFpsDANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO -TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDcwNzA1MDg0MjA3WhcN -MTUwNzI3MDgzOTQ2WjBfMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy -IEIuVi4xNzA1BgNVBAMTLkRpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp -ZCBlbiBCZWRyaWp2ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc -vdKnTmoKuzuiheF/AK2+tDBomAfNoHrElM9x+Yo35FPrV3bMi+Zs/u6HVcg+uwQ5 -AKeAeKxbT370vbhUuHE7BzFJOZNUfCA7eSuPu2GQfbGs5h+QLp1FAalkLU3DL7nn -UNVOKlyrdnY3Rtd57EKZ96LspIlw3Dgrh6aqJOadkiQbvvb91C8ZF3rmMgeUVAVT -Q+lsvK9Hy7zL/b07RBKB8WtLu+20z6slTxjSzAL8o0+1QjPLWc0J3NNQ/aB2jKx+ -ZopC9q0ckvO2+xRG603XLzDgbe5bNr5EdLcgBVeFTegAGaL2DOauocBC36esgl3H -aLcY5olLmmv6znn58yynAgMBAAGjggFQMIIBTDBIBgNVHSAEQTA/MD0GBFUdIAAw -NTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5kaWdpbm90YXIubmwvY3BzL3BraW92 -ZXJoZWlkMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIGABgNVHSME -eTB3gBQLhtYPd6NosftkCcOIblwEHFfpPaFZpFcwVTELMAkGA1UEBhMCTkwxHjAc -BgNVBAoTFVN0YWF0IGRlciBOZWRlcmxhbmRlbjEmMCQGA1UEAxMdU3RhYXQgZGVy -IE5lZGVybGFuZGVuIFJvb3QgQ0GCBACYmnkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0 -cDovL2NybC5wa2lvdmVyaGVpZC5ubC9Eb21PdkxhdGVzdENSTC5jcmwwHQYDVR0O -BBYEFEwIyY128ZjHPt881y91DbF2eZfMMA0GCSqGSIb3DQEBBQUAA4IBAQAMlIca -v03jheLu19hjeQ5Q38aEW9K72fUxCho1l3TfFPoqDz7toOMI9tVOW6+mriXiRWsi -D7dUKH6S3o0UbNEc5W50BJy37zRERd/Jgx0ZH8Apad+J1T/CsFNt5U4X5HNhIxMm -cUP9TFnLw98iqiEr2b+VERqKpOKrp11Lbyn1UtHk0hWxi/7wA8+nfemZhzizDXMU -5HIs4c71rQZIZPrTKbmi2Lv01QulQERDjqC/zlqlUkxk0xcxYczopIro5Ij76eUv -BjMzm5RmZrGrUDqhCYF0U1onuabSJc/Tw6f/ltAv6uAejVLpGBwgCkegllYOQJBR -RKwa/fHuhR/3Qlpl ------END CERTIFICATE----- -` - -func parseCertPEM(t *testing.T) (revoked *x509.Certificate) { - certPool := x509.NewCertPool() - ok := certPool.AppendCertsFromPEM([]byte(revoked_intermediate)) - if !ok { - t.Fail() - } - revoked = certPool.Certificates()[0] - return -} - -func loadRevokedList(t *testing.T) (onecrl *mozilla.OneCRL) { - oneCRLFile, err := os.Open(onecrl_location) - if err != nil { - t.Error(err.Error()) - } - defer oneCRLFile.Close() - oneCRLBytes, err := io.ReadAll(oneCRLFile) - if err != nil { - t.Error(err.Error()) - } - - onecrl, err = mozilla.Parse(oneCRLBytes) - if err != nil { - t.Error(err.Error()) - } - return -} - -func TestParse(t *testing.T) { - loadRevokedList(t) -} - -func TestCheck(t *testing.T) { - onecrl := loadRevokedList(t) - revoked := parseCertPEM(t) - entry := onecrl.Check(revoked) - if entry == nil { // this should provide an entry, since cert is revoked and in the provided sst file - t.Fail() - } - if entry.SerialNumber.Cmp(revoked.SerialNumber) != 0 { - t.Fail() - } -} - -func TestFetchLocal(t *testing.T) { - // bytes, err := os.ReadFile("testdata/records") - bytes, err := os.ReadFile(onecrl_location) - require.NoError(t, err) - - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write(bytes) - }) - server := httptest.NewServer(h) - defer server.Close() - - p := mozilla.NewProvider(server.URL) - - set, err := p.FetchAndParse() - require.NoError(t, err) - assert.NotNil(t, set.IssuerLists) - // assert.Len(t, set.IssuerLists, 251) -} - -func TestFetchRemote(t *testing.T) { - p := mozilla.NewProvider(mozilla.OneCRLDistPoint) - - set, err := p.FetchAndParse() - require.NoError(t, err) - assert.NotNil(t, set.IssuerLists) - - // test default - set2, err := mozilla.FetchAndParse() - require.NoError(t, err) - assert.NotNil(t, set2.IssuerLists) -} diff --git a/crypto/x509/revocation/mozilla/testdata/records b/crypto/x509/revocation/mozilla/testdata/records deleted file mode 100644 index 0c198e0872c..00000000000 --- a/crypto/x509/revocation/mozilla/testdata/records +++ /dev/null @@ -1 +0,0 @@ -{"data":[{"schema":1607462846244,"details":{"bug":"1680927","who":"dkeeler@mozilla.com","why":"Kazakhstan MITM (#3)","name":"Information Security Certification Authority CA","created":"2020-12-07T23:52:21Z"},"enabled":true,"issuerName":"MFYxODA2BgNVBAMTL0luZm9ybWF0aW9uIFNlY3VyaXR5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENBMQ0wCwYDVQQKEwRJU0NBMQswCQYDVQQGEwJLWg==","serialNumber":"KH3ODOPG96qjP/ll526pjIJKWds=","id":"e93dad8d-45ef-4174-bc5f-2cce9ce52c24","last_modified":1607539716735},{"schema":1606237258635,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"dmnAQKXSXYptTvdbyxROUqOQWJ0=","id":"3854a122-e277-4af3-8819-cf6e7d2bde38","last_modified":1606237252219},{"schema":1606237258260,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"GJF9m6GiOakqINltfXbZQtxKEGU=","id":"b00e2c36-61a3-4a00-b63b-e6355b86aed0","last_modified":1606237252063},{"schema":1606237257827,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Cvhc+o++pVw9AL6N9N0w6D7ygkQ=","id":"c1fc820f-b6fa-47bc-83fe-0de5842cf130","last_modified":1606237251907},{"schema":1606237257476,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"YUrgi0DHsxHYXt49k0VA2g==","id":"07110549-cea6-49b6-aee6-ffec223e88ca","last_modified":1606237251750},{"schema":1606237257131,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"Ae5fIk5ZxNFubPUxYw==","id":"17086fc0-bc58-40ee-8523-e2d76f855c11","last_modified":1606237251596},{"schema":1606237256765,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"c9pa+iPZP7qELgog9AHJ2G4k/F0=","id":"73cc9f1e-073e-4f9d-86dd-ba593662a14c","last_modified":1606237251440},{"schema":1606237256404,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"ReeMpfX7014KbBcz+Bi7VA==","id":"a70b4027-bd52-4437-a4f5-c4f8523d59a8","last_modified":1606237251285},{"schema":1606237256050,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"Nq+beJUJjRiUhESAu1k7k6Z0RT0=","id":"685ba4b6-398c-4ad9-9689-76fff19e53b6","last_modified":1606237251131},{"schema":1606237255684,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"Q6kODxh1MBAjWD4n6PuAue3GSw4=","id":"70b80622-a284-461b-a9e2-3dbd9c007dc2","last_modified":1606237250976},{"schema":1606237255322,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"Qd4GA1RV7pjIJpSgkKlGME8u/4c=","id":"eca7098d-b54e-46d4-b783-f8ec21706c93","last_modified":1606237250822},{"schema":1606237254923,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"LwO3QHf+WENPNhPDs41au1LN0w4=","id":"31c86b9b-97b4-4e8b-b036-0bb4b49290f6","last_modified":1606237250666},{"schema":1606237254567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"bomLaB2wkfxTPIzWP9gA5w==","id":"59885864-5341-4f5a-90f1-59055aca15f5","last_modified":1606237250506},{"schema":1606237254204,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"QAF04JJlL8YLqYHff02SmA==","id":"6263a3b5-3a6b-4fad-93f5-7a69c61562a7","last_modified":1606237250349},{"schema":1606237253826,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"QAF04JJ0ObjtC66DDuB/SA==","id":"3ba0026a-766a-48c1-a17f-d03ec43379fe","last_modified":1606237250194},{"schema":1606160498787,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1679183","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"GxL0QbvG2zbxZzhJGclbCxYkXEc=","id":"41d4025d-a847-4b7d-bd0e-6befd03c6460","last_modified":1606237249950},{"schema":1605805286524,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"AkSadIfHzbm3VI4r7Gsfyg==","id":"2b1efa09-4c1b-4d9c-9cea-ef42544b4e2c","last_modified":1605805266213},{"schema":1605805286123,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxKjAoBgNVBAMTIUlkZW5UcnVzdCBQdWJsaWMgU2VjdG9yIFJvb3QgQ0EgMQ==","serialNumber":"CgFCgAAAAVEl13NhAAAAAg==","id":"9227e662-5fd7-4cf7-a4f5-d6101493251b","last_modified":1605805266047},{"schema":1605805285768,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABNuk6OrM=","id":"8326925e-0757-4f5d-b837-5557ffd6be0a","last_modified":1605805265875},{"schema":1605805285386,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"CvZcvnGmEFQSk2xCwhibpw==","id":"ea049bf5-9917-4bfd-a3a5-b4f776ebc61f","last_modified":1605805265709},{"schema":1605805284959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdCIENB","serialNumber":"MwAAABbN/xkAVVRYtwAAAAAAFg==","id":"7a2e0fee-04cb-45bd-ba87-c080899ae002","last_modified":1605805265543},{"schema":1605805284605,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABNumCOV0=","id":"548a971f-0a10-404a-9c23-6b95c7a3093d","last_modified":1605805265376},{"schema":1605805284256,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"H4YDb0uIAMdUnNyPR/pbe3BPlSU=","id":"c96bdfc7-55dc-45e2-840a-9554bbad29b4","last_modified":1605805265200},{"schema":1605805283910,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGMxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xNDAyBgNVBAMMK1N0YWF0IGRlciBOZWRlcmxhbmRlbiBEb21laW4gU2VydmVyIENBIDIwMjA=","serialNumber":"erEwoq3oXeVG3OPjTKvIN7H3JdQ=","id":"3a7e18e9-b8a4-413d-9af6-7ab91773332b","last_modified":1605805265024},{"schema":1605805283559,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BCshiSJ3NHQyikS/bV3uPQ==","id":"3cb9bf01-1dc7-4f4a-ab59-6f4aedbb13f2","last_modified":1605805264855},{"schema":1605805283196,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"dgvbZsDHLBWQOFhRyINfIm288GM=","id":"d88b550b-1601-495c-8416-754dcaa1c786","last_modified":1605805264686},{"schema":1605805282841,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"dR4+7KSgWczvgqiIFI922Q==","id":"ffd6f99d-e200-4013-87ad-386d7f8ab887","last_modified":1605805264522},{"schema":1605805282467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"AenYn3DXZQryO4NWdA==","id":"036c673a-922b-4d5b-8ac2-a677c16f1739","last_modified":1605805264356},{"schema":1605805282124,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"AenYn2YG9Tfnb02L9w==","id":"26aeffc6-86c2-419e-90a0-f1a9d741985c","last_modified":1605805264186},{"schema":1605805281691,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENB","serialNumber":"DxaDT4KRkeMq/3spObeaUg==","id":"0741e031-349c-4928-afa5-7a98a5f89928","last_modified":1605805264018},{"schema":1605805281341,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQQ==","serialNumber":"BkoduoMprQURTuDY6pi+fA==","id":"9bad30d8-9199-432e-841f-37a48d5fc662","last_modified":1605805263851},{"schema":1605805280996,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"dR4+6PDu0/tJvB0t+q2Tjw==","id":"c27287e9-1385-490f-bc19-1e8d45a0a89a","last_modified":1605805263680},{"schema":1605805280608,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"b6PMduOT1igm2b5XrSbN1ayRYD0=","id":"823b3acc-228f-43ce-a7b4-151cf75934d3","last_modified":1605805263510},{"schema":1605805280254,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"YVQpZ/rcAgCYQ5mgLIWRrgmF5YY=","id":"4503d351-700c-4af5-9b32-a3e8314572f0","last_modified":1605805263340},{"schema":1605805279895,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"CgZFWoVH8W4JmjaEZIlOZA==","id":"339013cc-143e-4922-a688-8b6478c5c01e","last_modified":1605805263172},{"schema":1605805279538,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBSb290IENB","serialNumber":"HlNa/3/6dnNEqFtSStnQKX1dumU=","id":"d45e5544-227f-437c-921e-bbb75b6ddb0c","last_modified":1605805263004},{"schema":1605805279149,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DXEchC/p1n6dzCKiHLZc3w==","id":"e0d2b6bf-e37e-4179-91d0-8c1ab6355075","last_modified":1605805262835},{"schema":1605805278768,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGMxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xNDAyBgNVBAMMK1N0YWF0IGRlciBOZWRlcmxhbmRlbiBEb21laW4gU2VydmVyIENBIDIwMjA=","serialNumber":"EHDoZA3ClX5CJu5GKdvXUZn+Hr4=","id":"69aa0c32-b427-4e45-a7e3-3aa5bef3e847","last_modified":1605805262664},{"schema":1605805278367,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"PdQW/4AvIwpSzL1h30myhgjnfno=","id":"afa81c00-2b9c-4acb-b206-dc75bed4d7df","last_modified":1605805262495},{"schema":1605805278024,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"RUME8OY/YBHyokbgxoTKpPcoiHY=","id":"9f47e911-04fe-49e5-bc72-179f32d65702","last_modified":1605805262326},{"schema":1605805277676,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"BeizThxeIodIgkMRs8LrVw==","id":"f863e679-95a7-4481-a5de-11b1fddd1798","last_modified":1605805262155},{"schema":1605805277295,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"SYSzK6SV0MYd40vPFNOjWu5QhkQ=","id":"92821be2-e278-4214-b517-1cbc171d1241","last_modified":1605805261980},{"schema":1605805276938,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"TeYBCZy0d/TPcAJ6FN6M20qNJKc=","id":"665cb523-8317-466a-8a04-7893e9e68a7f","last_modified":1605805261806},{"schema":1605805276583,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"Dy7r7RLmbxPEc/M/+nbVCw==","id":"ce7389c4-d142-4258-9e1b-a30ee9398926","last_modified":1605805261636},{"schema":1605805276096,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzM=","serialNumber":"ODVFFOhzXWvRkIGhqNL3P4BwTRA=","id":"70bec368-2a5c-4ca4-b210-78ae19fff42f","last_modified":1605805261454},{"schema":1605805275716,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"TbiYNjM7FrxEHV9PxgvGfc/wvSg=","id":"32b2fee6-46df-4686-acca-8ed67e5d8a42","last_modified":1605805261283},{"schema":1605805275306,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DCzgwS1angzJReCv7Xcalg==","id":"17d4fa79-78bf-4472-8a80-65151706027a","last_modified":1605805261110},{"schema":1605805274890,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"BmdUhbrY7ZII2zyybFAaEw==","id":"db912b82-5b3c-4bf9-877c-b35ea22edbee","last_modified":1605805260941},{"schema":1605805274355,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"AsGJSGnUUCnrODgadbthZw==","id":"09a57059-648a-4b0a-a021-e3a43d057d38","last_modified":1605805260773},{"schema":1605805273804,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"SKQC3bXe/VCsz8D88T8=","id":"8c9f276c-18ac-43d2-be34-b2fc879c6190","last_modified":1605805260607},{"schema":1605805273245,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"d+erf7BRCIYZoI7WwMt/6rzpJBY=","id":"db99b9fd-21b8-465d-beb1-3d62c0d02b02","last_modified":1605805260442},{"schema":1605805272681,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdBIENB","serialNumber":"QyMLpAAAAAAABg==","id":"46bde686-bcd3-40e2-b870-94d077364822","last_modified":1605805260274},{"schema":1605805272154,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdBIENB","serialNumber":"GCS4aQAAAAAACw==","id":"cd70af23-8e21-4c6e-853f-663a72ace8ba","last_modified":1605805260099},{"schema":1605805271578,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"D5JnAg9adbdm5Das0NhZBA==","id":"4096586d-5ab7-4d99-8cad-0851589758d5","last_modified":1605805259906},{"schema":1605805271001,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzM=","serialNumber":"dJ4w/GwP08WekbUIXvYTsQrO+a8=","id":"2ed55472-2fca-4f88-a4d3-6430ebcfe887","last_modified":1605805259742},{"schema":1605805270416,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGMxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xNDAyBgNVBAMMK1N0YWF0IGRlciBOZWRlcmxhbmRlbiBEb21laW4gU2VydmVyIENBIDIwMjA=","serialNumber":"DHG5F7l+J207REqX6P129dCmM1Y=","id":"c5862b61-90db-45fd-be2e-191654adafcc","last_modified":1605805259578},{"schema":1605805269781,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBSb290IENB","serialNumber":"mJjo","id":"15ccff90-0369-41b0-9c4a-4c827efa9ede","last_modified":1605805259414},{"schema":1605805269328,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"Bf8hBaUt76ku6AB5KoFdkA==","id":"aa17e7fa-44bd-42f3-b581-959a186a421b","last_modified":1605805259251},{"schema":1605805268949,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQQ==","serialNumber":"BoL7H4F3dqV5kSw+2RDv8Q==","id":"ab74320e-97a9-46f8-ad2c-56b559c97b5d","last_modified":1605805259087},{"schema":1605805268441,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"dai5tSMbn5UK7WK6+0ZxRw==","id":"68c90a6f-5401-44b7-b25d-e54377d96f7a","last_modified":1605805258921},{"schema":1605805268081,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"GvbZeo/wso3urAGlJMh6bzLnnfY=","id":"a9026db6-597b-40d2-9d83-bca127f77906","last_modified":1605805258754},{"schema":1605744672266,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1678378","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdBIENB","serialNumber":"YQbgdgAAAAAABA==","id":"5e2484ae-7825-4ed0-8f75-00ad399983c3","last_modified":1605805258590},{"schema":1604163626757,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1674587","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"Irmw1g==","id":"af04f4c1-0721-4205-b839-a3694ceb5f95","last_modified":1604163622432},{"schema":1604163626424,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1674587","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MGAxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMTAvBgNVBAMMKFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBJbnRlcm1lZGlhaXIgQ0E=","serialNumber":"akWWZTytiy58nyLOsqpnaQ==","id":"9b13e978-d61b-4572-8227-5a297f82a11e","last_modified":1604163621932},{"schema":1604163572181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1674587","who":"","why":"","name":"","created":""},"enabled":false,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNTETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"Ae5fInnr9AhpWVIjkw==","id":"3719f39f-d274-4708-96d8-75eca5eab6f4","last_modified":1604163621422},{"schema":1599939719570,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1664854","who":"jjones@mozilla.com","why":"","name":"revoked.badssl.com certificate","created":"2020-09-14T18:43:23Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQQ==","serialNumber":"A3G1iob2zpw+y3v0L5II/A==","id":"53648e4e-4a7e-4c75-858e-cab93f2a31d1","last_modified":1600109031945},{"schema":1591649664675,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AWGuIAXOPxJ++I3XJRux","id":"c0f8f918-79ab-482a-9706-e23f19c61e97","last_modified":1591649665036},{"schema":1591649664299,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxaI50lNZi","id":"a848ed94-c8c9-4f2d-afaf-b148b98db582","last_modified":1591649664666},{"schema":1591649663925,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxaePNG8wi","id":"01de91b2-85b7-44d8-8a29-6e92c2030014","last_modified":1591649664289},{"schema":1591649663553,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzM=","serialNumber":"ZyJMAoxOQNnj8J4Hj3cObklOwII=","id":"e993fef8-58b5-4dd5-9d85-c158fea34a38","last_modified":1591649663915},{"schema":1591649663183,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzM=","serialNumber":"NVdKOsmxSGeTCfVPNC95i7XTw/4=","id":"5b7b7dfc-f4ff-4d72-9d4e-9ee696b6306f","last_modified":1591649663543},{"schema":1591649662815,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHAxCzAJBgNVBAYTAk5MMRcwFQYDVQRhDA5OVFJOTC0zMDIzNzQ1OTEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xJjAkBgNVBAMMHVF1b1ZhZGlzIFF1YWxpZmllZCBXZWIgSUNBIEcx","serialNumber":"JN7EJQf8huzLxEjHdisrDOgr0sM=","id":"36f591c2-4c2a-4514-a7da-dcef49e32884","last_modified":1591649663173},{"schema":1591649662438,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHAxCzAJBgNVBAYTAk5MMRcwFQYDVQRhDA5OVFJOTC0zMDIzNzQ1OTEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xJjAkBgNVBAMMHVF1b1ZhZGlzIFF1YWxpZmllZCBXZWIgSUNBIEcx","serialNumber":"Vuxo8erTcb0tPvSne8vm7poAGfg=","id":"4ca3a08c-7c00-4006-9afe-3233f2be1d1e","last_modified":1591649662805},{"schema":1591649662070,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABcxl+EFyHWQKE=","id":"e5f98ef5-611a-457c-876f-fef1890ea5f3","last_modified":1591649662428},{"schema":1591649661696,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABak8+W6/V88R0=","id":"0a0a2bb9-943b-4e99-aad6-608eff1fc6e8","last_modified":1591649662061},{"schema":1591649661328,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABb3uz2uVMNhTQ=","id":"327af663-e668-4828-8223-42d7cbec9bd6","last_modified":1591649661686},{"schema":1591649660960,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"Dw==","id":"ec09837a-c496-4f2a-a2e3-d7b8255d8aa4","last_modified":1591649661318},{"schema":1591649660590,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"FQ==","id":"310af8c7-a837-4f5d-acd8-f150fdb1a228","last_modified":1591649660950},{"schema":1591649660220,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"AQ==","id":"70d7ef28-9c7b-4737-bf78-12469fc8c17e","last_modified":1591649660581},{"schema":1591649659854,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"BQ==","id":"18be7382-53ee-4963-b3bd-fde64e8aa4de","last_modified":1591649660211},{"schema":1591649659485,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"Ag==","id":"b0757116-5f7e-4633-917b-3ac2ba7663e4","last_modified":1591649659844},{"schema":1591649659106,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"Aw==","id":"3b0ad68b-7bd2-499c-9a38-54f6a33a74c2","last_modified":1591649659475},{"schema":1591649658734,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"DQ==","id":"3fd06aee-629f-4979-8323-0465a9fa5500","last_modified":1591649659096},{"schema":1591649658361,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxKjAoBgNVBAMTIUlkZW5UcnVzdCBQdWJsaWMgU2VjdG9yIFJvb3QgQ0EgMQ==","serialNumber":"APTRqBUm1okACgR2cZ8cfyQ=","id":"8729e8d8-fe54-4368-8514-134c5d170341","last_modified":1591649658724},{"schema":1591649657992,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"AeNmeE7qYUep9C4NnA==","id":"15d07b9c-17fb-4e80-abf0-2f1e717492d0","last_modified":1591649658351},{"schema":1591649657620,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"SBtqDm4P/739RPqw/wc=","id":"38ebfa60-5de1-4b3c-af35-c4418e230210","last_modified":1591649657979},{"schema":1591649657251,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"AeEjUghuH7H0d7NMnA==","id":"152d4c2b-ce88-4a14-ad3f-57fcf1f2b163","last_modified":1591649657610},{"schema":1591649656882,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"AeUosKc0AFkLsGdjaw==","id":"8e2ca07d-ab48-4d70-ae2a-c2a6e389f5e6","last_modified":1591649657241},{"schema":1591649656453,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeyFg==","id":"bf068164-e35f-4bec-b1cc-cc7ff5379682","last_modified":1591649656872},{"schema":1591649656080,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"eUvtSxcPn58fPCIEBd5eFw==","id":"83bc86bf-c02f-448a-97d3-7b81b115d16e","last_modified":1591649656443},{"schema":1591649655703,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"APReKEnjxshvEQowJWkFghM=","id":"68428bfd-380c-4b10-9ec1-183f6b40ce05","last_modified":1591649656070},{"schema":1591649655330,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0E=","serialNumber":"AtusdpjPnzfY+uarbdje+A==","id":"108255c9-fab2-4918-88b9-d26df1cac1f2","last_modified":1591649655693},{"schema":1591649654954,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"GA==","id":"557d080d-b0ea-4b1e-b4c0-960ca0cd3175","last_modified":1591649655320},{"schema":1591645303251,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=","serialNumber":"GA==","id":"b6826693-3d91-40e3-8d2b-265e4c7cda80","last_modified":1591649654943},{"schema":1584034823601,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"QDHn+nHfbVLgWJSmBrXX8w==","id":"d4ebcb06-cb47-45ae-b5f9-d6674826e686","last_modified":1584034823983},{"schema":1584034823229,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"M0ZhG4oxvRRWcqjOeSs9yA==","id":"29bb0c13-74dd-4a55-9883-0e961e1942ea","last_modified":1584034823592},{"schema":1584034822846,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"Z8aU3fhNIStWcqv0tJZTgg==","id":"ca822ca1-0b9c-4524-a953-d101f593eba7","last_modified":1584034823220},{"schema":1584034822464,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"exeWtGPKX/5WcqdQhOc8fQ==","id":"4806b099-4614-40a8-a483-e9e6188116d8","last_modified":1584034822836},{"schema":1584034822061,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"BQjRlltFCk5Wcqhsy4QVhw==","id":"e3d96b23-470d-4cb3-8f5d-b5270c783e0d","last_modified":1584034822448},{"schema":1584034821655,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"Gf80Vp02a6H2bo2VMu4F0FW53R0=","id":"3dd81a10-316e-4311-81f4-6ba5dabf5ae7","last_modified":1584034822049},{"schema":1584034821215,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzM=","serialNumber":"YnphsQ5/Xye+O+telM9/9Eje4cU=","id":"ee4e0d21-2e0e-47e4-a708-9a6225d9069f","last_modified":1584034821631},{"schema":1584034820824,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzM=","serialNumber":"FO1+kHW2roaOGjsCT4qUr8j127o=","id":"5af568ce-9c5a-430c-aba1-b68ceabe05ff","last_modified":1584034821205},{"schema":1584034820412,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"CY639U9sn0sX18dB44VklbKesdk=","id":"00ef184d-e7d9-4dc3-98d6-2db2b75087ae","last_modified":1584034820814},{"schema":1583869297369,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"BuhGJy8fCo/RhFzjafbV","id":"0b3cb4f0-b5ff-4816-adf3-a1698c3458f9","last_modified":1584034820403},{"schema":1582566021219,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AWBLIvZ2PwkB7gSDa5c8","id":"b3b20ec6-e123-4a70-92ea-cb05df99ef75","last_modified":1582566021574},{"schema":1582566020850,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AV/EmsRwXPDZBTXjz0SR","id":"74ac3328-fd34-4415-ba06-c228eae47e78","last_modified":1582566021209},{"schema":1582566020468,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AWWEyekrgDP1hvA8XKDc","id":"c793250e-087c-4160-8177-344d33fd3577","last_modified":1582566020841},{"schema":1582566020072,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AJk4uNYGKOpZLiYBD9Jm6BE=","id":"fff43ffb-3ec4-4644-9da7-f936fa622581","last_modified":1582566020459},{"schema":1582566019700,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"AIFRrXKLZ6V/pFUkjYHTV/k=","id":"12593d1d-d952-4029-908f-eb19f099740c","last_modified":1582566020063},{"schema":1582566019323,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"EGhKDYboQ1ktFnRqiBUvgQ==","id":"e1d374e5-cdba-4122-b154-0daee677c7ad","last_modified":1582566019691},{"schema":1582566018953,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"NXkdh5JRbWGxHEvvr3bB2g==","id":"88c23adc-fb99-49f4-802f-8ed1e55fa814","last_modified":1582566019314},{"schema":1582566018565,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"APhdLxkMYJ8UlLKN+cHR50w=","id":"fc817b05-b53b-4642-83d1-365b983ec797","last_modified":1582566018945},{"schema":1582566018184,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"ANDXcnKaBBeX+J7a44L5HxE=","id":"804079f6-b969-4a06-a646-d1307ab4b213","last_modified":1582566018555},{"schema":1582566017800,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDMgRzM=","serialNumber":"PGx6vOZ0LowycWshA7l2/cS9l5E=","id":"787c516b-e616-459d-b9c5-04473ac6d15b","last_modified":1582566018174},{"schema":1582566017432,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDMgRzM=","serialNumber":"bKpOjcdardvXVCsjEOCqoP1/zsE=","id":"eaa05242-5992-4dc8-aa3d-1063279ec952","last_modified":1582566017792},{"schema":1582566017047,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Rj+ThwsAA8DqoQLXSaqqElyK9P4=","id":"5e3489f3-78b6-48ed-afd7-ccb86042749f","last_modified":1582566017423},{"schema":1582566016663,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"DA==","id":"8b502698-fba2-4372-9e7d-988420335d31","last_modified":1582566017037},{"schema":1582566016231,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"Dg==","id":"1d856404-8fcc-498e-8f8a-c2016e6d7c55","last_modified":1582566016654},{"schema":1582566015857,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"Cw==","id":"ccd96d5a-16fe-4fd8-bd6e-294a66abd88e","last_modified":1582566016222},{"schema":1582566015470,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odQ==","serialNumber":"BA==","id":"d572f4d1-985f-4ac4-8a8f-1a17109e0504","last_modified":1582566015848},{"schema":1582566015097,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"ZG/V3gQ1QzdJo6nRSP5AjQ==","id":"437f5819-57b9-4aa5-b4a2-89adda81489b","last_modified":1582566015461},{"schema":1582566014726,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"TkUbErttua5HoElQBoHrfg==","id":"f3c4284d-2654-478c-9a44-a99544a88e88","last_modified":1582566015087},{"schema":1582566014354,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"UnMUjvgeTcJJkqVP72pF8w==","id":"a5b1499f-c072-4a3d-9033-22bbdc09c23e","last_modified":1582566014715},{"schema":1582566013971,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"VUQCtMaN0r1Jo6pasF0CjQ==","id":"6a554d48-b068-47bb-931d-22b8cb7b66d0","last_modified":1582566014345},{"schema":1582566013606,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAk5MMUQwQgYDVQQKDDthZ2VudHNjaGFwIENlbnRyYWFsIEluZm9ybWF0aWVwdW50IEJlcm9lcGVuIEdlem9uZGhlaWRzem9yZzEYMBYGA1UEAwwPWm9yZyBDU1AgQ0EgRzIx","serialNumber":"AOc8WaTzibK6426cQCzYSn0=","id":"1570bd10-b7c0-4dbd-9e15-ba1e0115e9c2","last_modified":1582566013962},{"schema":1582566013230,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSNA==","serialNumber":"AfCcW3AFptyG4vme8w==","id":"03ca2e4b-c3ab-4bc0-8ce1-01bd8f454496","last_modified":1582566013597},{"schema":1582566012856,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSMw==","serialNumber":"AfCcW0UoBqS7QoIgZQ==","id":"b3615945-89df-482d-b8cf-68df333347de","last_modified":1582566013221},{"schema":1582566012488,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"AenYn3utvYQ+obXTYQ==","id":"0f8df12d-f783-4562-98fe-d57baeea9889","last_modified":1582566012846},{"schema":1582566012112,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"AecHzeH0hsl7/sQXWA==","id":"c6225619-2a00-4f0f-844c-25be3e08ab8c","last_modified":1582566012478},{"schema":1582566011728,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"AecHzcaPEeFvu7X4TQ==","id":"f66167d5-097d-4b1f-bfb8-667015b1e683","last_modified":1582566012099},{"schema":1582566011356,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"SETcxilXmeYyN/2STTs=","id":"07dcda66-29df-4978-b75a-e3a0dd844b54","last_modified":1582566011720},{"schema":1582566010982,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"AeEjUi4YCM8xJiOwqA==","id":"7551c683-55c9-4b0f-9d65-a1db506f682b","last_modified":1582566011347},{"schema":1582566010616,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"Yxhd22Oak3mBIvwX0BVTSfw=","id":"bd9a292d-f2c4-4308-be5a-687bc05da029","last_modified":1582566010974},{"schema":1582566010243,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"EdccO1mbICQnbPFsBI2427NJ","id":"2eb7cd83-059a-40ff-ab3e-146204bc3abc","last_modified":1582566010607},{"schema":1582566009869,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"AfJAQQv5hQk4X1fUHQ==","id":"5f42b2aa-15a8-42a0-b469-f104e228af12","last_modified":1582566010234},{"schema":1582566009491,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"AfJAQRZysbylo3/lCg==","id":"77ac5cd3-7279-4240-b4eb-62004c39d6bf","last_modified":1582566009861},{"schema":1582566009112,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"Ae5fFxAYBjmCt/6FYA==","id":"c21f9163-b036-4ac7-b2e9-f7ab2b665298","last_modified":1582566009475},{"schema":1582566008742,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"GAoX7ScPfxz8YoiFM5eqvg==","id":"e8a4b4f0-615a-4bf0-b48e-93b5884296f9","last_modified":1582566009103},{"schema":1582566008341,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemYQ==","id":"15a865a0-d558-4f88-9892-3a271a5f6528","last_modified":1582566008733},{"schema":1582566007956,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByekcQ==","id":"7d902b2c-9b95-4a5e-8a31-08bc5da7bd3e","last_modified":1582566008332},{"schema":1582566007571,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"RlOxph66LcejLvk5Wk74jA==","id":"d796075a-7084-4a8c-840b-8dc6e026f461","last_modified":1582566007944},{"schema":1582566007187,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=","serialNumber":"BJJx","id":"04ad7a19-5455-4052-8002-c9de365cde8e","last_modified":1582566007562},{"schema":1582566006822,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"BHpT","id":"1b8b4d93-eaf2-4424-a34b-2f1968461dc5","last_modified":1582566007178},{"schema":1582566006451,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"BHpR","id":"f9a51bb4-e3f9-4932-b1f5-631c3bdccdc1","last_modified":1582566006814},{"schema":1582566006061,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"BHpS","id":"ae949154-cc09-479b-b394-a3f30a5390a1","last_modified":1582566006442},{"schema":1582566005683,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"BHpU","id":"ed327a30-25e2-4875-a463-4a15b1faaa1a","last_modified":1582566006052},{"schema":1582566005308,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"HkSTzpMySJNT6+Pl3MpFlQ==","id":"75c8f23b-549a-403b-be9d-b731572438a5","last_modified":1582566005674},{"schema":1582566004927,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"TLBJ4w6JFdOEMMEXiHXM1A==","id":"d00ae455-12cf-4ea5-ae0c-a2f06705f821","last_modified":1582566005299},{"schema":1582566004551,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"SQI5AVoNzAF3OWyiM2Cj4ljeFC0=","id":"b8ec1e7e-6280-458d-9c29-a3e851f00122","last_modified":1582566004918},{"schema":1582566004167,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"Bx243avyP23U1FKvQBJ36w==","id":"0e1f48ab-30d2-4e63-9780-9b6672a6ca1a","last_modified":1582566004543},{"schema":1582566003760,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"eWPQh1DffhyNUeYDl8YVtA==","id":"1aa0c34a-ddd4-4cf0-9279-64d791e62070","last_modified":1582566004158},{"schema":1582566003376,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"LiPbNfQ597/RWOBNV1MXoA==","id":"829e3d9e-06f4-4002-a810-36dd34eee245","last_modified":1582566003748},{"schema":1582566002989,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=","serialNumber":"BHpY","id":"557694d9-82a5-4dc3-a735-b3f1af73aded","last_modified":1582566003366},{"schema":1582566002614,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=","serialNumber":"Btbu","id":"f5c9bdce-783b-4f33-8e9f-9612f211c845","last_modified":1582566002979},{"schema":1582486896281,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBHbG9iYWwgU2VydmljZXMgQ0E=","serialNumber":"Or+7fO17j//ZhiuTTAKvlg==","id":"1409bc48-a188-478f-9155-3c123a564ed6","last_modified":1582566002601},{"schema":1581547557131,"details":{"bug":"1614521","who":"jc@mozilla.com","why":"Migrate NSS-exceptions to OneCRL - Explicitly Distrust TURKTRUST Mis-issued Intermediate CA 2, Bug 825022","name":"","created":"2020-02-12T18:21:41Z"},"enabled":true,"issuerName":"MIGsMT0wOwYDVQQDDDRUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU3VudWN1IFNlcnRpZmlrYXPEsSBIaXptZXRsZXJpMQswCQYDVQQGEwJUUjFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEthc8SxbSAgMjAwNQ==","serialNumber":"CGQ=","id":"f48493ce-ff35-4488-bcf3-d7346a1141a2","last_modified":1581547557572},{"schema":1581547556681,"details":{"bug":"1614521","who":"jc@mozilla.com","why":"Migrate NSS-exceptions to OneCRL - Explicitly Distrust TURKTRUST Mis-issued Intermediate CA 1, Bug 825022","name":"","created":"2020-02-12T18:21:29Z"},"enabled":true,"issuerName":"MIGsMT0wOwYDVQQDDDRUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU3VudWN1IFNlcnRpZmlrYXPEsSBIaXptZXRsZXJpMQswCQYDVQQGEwJUUjFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEthc8SxbSAgMjAwNQ==","serialNumber":"CCc=","id":"b9e6b58e-c59b-43d4-a0fd-40fcadf0b3ac","last_modified":1581547557115},{"schema":1581450099900,"details":{"bug":"1614521","who":"jc@mozilla.com","why":"Migrate NSS-exceptions to OneCRL - Explicitly Distrust DigiNotar Root CA","name":"","created":"2020-02-12T18:20:39Z"},"enabled":true,"subject":"MF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQKEwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubA==","pubKeyHash":"qQOvjAe7kbDZ4/OjDG1TM5/FvUfl1r20dlmIYMBooCQ=","id":"ebb80027-85c8-4050-9811-0652c73e3b77","last_modified":1581547556665},{"schema":1575764438461,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTI=","serialNumber":"CvPmEkBHF1I=","id":"2712cf5f-ee17-419d-9f34-4765019a8096","last_modified":1575764438822},{"schema":1575764438089,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"AKYNiDIZo/1Z","id":"5e3cd56a-8d87-4c27-bbce-10f8a606dddf","last_modified":1575764438449},{"schema":1575764437718,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGcMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0x","serialNumber":"AMEqE1/Azg/O","id":"9f4ca90c-4cce-4c50-a983-fe2699084e84","last_modified":1575764438077},{"schema":1575764437346,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTI=","serialNumber":"AILD6oiQKBkO","id":"dd14f3ab-2dea-4a49-983c-049f41a2f0c2","last_modified":1575764437705},{"schema":1575764436972,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"ANXTyHU0MhfU","id":"1c2f9486-f4b0-45a3-9e2f-7fc13a3034ae","last_modified":1575764437333},{"schema":1575764436597,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"NUuDOhKpuOw=","id":"65ec956e-d17e-4798-85df-a8aec5ec1727","last_modified":1575764436959},{"schema":1575764436224,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AL8nS46x5IonF4Zd2FEJXQ==","id":"ca7aa8e1-098e-49d7-85c2-b5eecb2ba9b5","last_modified":1575764436585},{"schema":1575764435856,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCruw==","id":"927c3aed-3e02-4cb0-bd37-b6edca4d7be3","last_modified":1575764436212},{"schema":1575764435486,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGrMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjEzMDEGA1UEAxMqVHJ1c3R3YXZlIE9yZ2FuaXphdGlvbiBJc3N1aW5nIENBLCBMZXZlbCAyMR8wHQYJKoZIhvcNAQkBFhBjYUB0cnVzdHdhdmUuY29t","serialNumber":"a0nSBQ==","id":"12307747-aa87-4f71-a288-fbb2d746c962","last_modified":1575764435844},{"schema":1575764435118,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"If8VaaoKoUovkCLO8Xxepg==","id":"019c646f-10d4-4a2c-98d0-e4d099b695a3","last_modified":1575764435474},{"schema":1575764434744,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"KQiQ7Gy+wFpJo6kX14gDJA==","id":"f674ff8a-8512-424b-a484-92b1d37eaf02","last_modified":1575764435106},{"schema":1575764434376,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"Kjk8JSCZz05Lc99cVI4VZA==","id":"577dcd25-091f-40b8-be75-857c51310715","last_modified":1575764434732},{"schema":1575764434008,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNvbQ==","serialNumber":"GlpqEDdi55FMvqfsM5o69Q==","id":"96718c7b-a7a0-4df7-81fb-142c0913297f","last_modified":1575764434364},{"schema":1575764433632,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxKjAoBgNVBAMTIUlkZW5UcnVzdCBQdWJsaWMgU2VjdG9yIFJvb3QgQ0EgMQ==","serialNumber":"IxyzTMi3hUiMqMKFEVmUsA==","id":"df4285cb-d4ec-46da-9cb7-d999c14a2a64","last_modified":1575764433996},{"schema":1575764433266,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQgAAAUitpA75AAAAAg==","id":"98b5110e-5ff7-4637-8048-337de479ddc1","last_modified":1575764433619},{"schema":1575764432895,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxJzAlBgNVBAMTHklkZW5UcnVzdCBDb21tZXJjaWFsIFJvb3QgQ0EgMQ==","serialNumber":"AKuJlbkX3duYPoRHyxCLixE=","id":"9c624327-49e7-45d5-9989-e1befff3a995","last_modified":1575764433254},{"schema":1575764432528,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQgAAAUjHb/QhAAAAAg==","id":"1ebd8951-a677-4455-a63c-b1067a8c39ff","last_modified":1575764432883},{"schema":1575764432148,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxKjAoBgNVBAMTIUlkZW5UcnVzdCBQdWJsaWMgU2VjdG9yIFJvb3QgQ0EgMQ==","serialNumber":"APkwq5XRBo9G6W+Me8AbALI=","id":"f8ef2d36-8449-43fa-a771-37446f1e8365","last_modified":1575764432515},{"schema":1575764431743,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"R8MQUj1TSc3d6WuO8n8=","id":"a4882416-9b70-43ba-a958-0a83ae056b28","last_modified":1575764432135},{"schema":1575764431368,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJ/vSI2Q=","id":"685a6776-16b3-4463-9df7-008c8a4fab4a","last_modified":1575764431726},{"schema":1575764430998,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hORY=","id":"66ef4cf4-6934-4c0d-8f59-208ef6ed9a0e","last_modified":1575764431356},{"schema":1575764430632,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hPWs=","id":"05298fda-f0a3-4fa2-9345-9b155f8ac2a2","last_modified":1575764430985},{"schema":1575764430260,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGPC4=","id":"395befa8-cc25-4a09-a1c2-15280fd295e7","last_modified":1575764430620},{"schema":1575764429874,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABIBnBkGY=","id":"01dba4b4-1925-4382-9428-6c1ac594421e","last_modified":1575764430248},{"schema":1575764429479,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hO1g=","id":"9f4bd983-d203-40ee-861b-bd9de6740eea","last_modified":1575764429861},{"schema":1575764429115,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"Rea3r9ymcb22XRTz2sA=","id":"29e9a3db-3c28-4c21-855d-a90dcacf30de","last_modified":1575764429467},{"schema":1575764428736,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABMxvQrsk=","id":"98968b25-36b9-4973-8297-1c6d3c53523e","last_modified":1575764429101},{"schema":1575764428368,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGQLI=","id":"0737d7ed-405d-43a9-bf11-e0d676fe3a18","last_modified":1575764428724},{"schema":1575764427997,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABM6da+eQ=","id":"b0c360b2-8d9b-4810-aada-9c74747559ab","last_modified":1575764428354},{"schema":1575764427615,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABK84yimo=","id":"903326e6-d357-44c7-a48f-559f97fc61c9","last_modified":1575764427985},{"schema":1575764427240,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABMxvQqqM=","id":"7ba7d48b-afaa-42be-87b2-d44718d6c896","last_modified":1575764427603},{"schema":1575764426868,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"Rea3w+z9S6JLMemr8IU=","id":"273eb9b0-c06e-4950-bf46-b2ea8ee0bd01","last_modified":1575764427228},{"schema":1575764426498,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGUAQ=","id":"65bcc99d-7d0f-4337-bcb5-1ccd788bec65","last_modified":1575764426856},{"schema":1575764426110,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"Ae5fFX7QOMo4XX885w==","id":"4a7dd82f-32e4-4a9d-85a6-5a6eec9f886c","last_modified":1575764426485},{"schema":1575764425712,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMzg0IC0gRzQ=","serialNumber":"Ae5fFZoAV4HO31tqWQ==","id":"c7c75e4a-0358-4533-a7d3-db856f1293c5","last_modified":1575764426098},{"schema":1575764425341,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"R8MQAMBL+oomVLdB7Cs=","id":"2c1850a5-b636-4ed1-99d7-7f9b4174d259","last_modified":1575764425699},{"schema":1575764424967,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"AewckkDe/S5AXXxHdA==","id":"ed050f24-eca7-46a3-bf94-9c91a460c7d3","last_modified":1575764425329},{"schema":1575764424593,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"SKQC3+1iPpeb8z1VOJk=","id":"ca502e89-7dc2-43d8-84eb-c5a16f6001c6","last_modified":1575764424954},{"schema":1575764424225,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMzg0IC0gRzQ=","serialNumber":"AenYpMwYI2wqWMGvjA==","id":"8f0a9c13-700c-41e6-b10f-4403a70f1204","last_modified":1575764424581},{"schema":1575764423851,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"AenYpKYtKygROYKpTQ==","id":"b5d201b0-f01c-4690-a327-21ac922697af","last_modified":1575764424212},{"schema":1575764423478,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABRE7wSlU=","id":"2717db18-3442-4354-a639-2cdd657046a6","last_modified":1575764423839},{"schema":1575764423112,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"R8MP/4phmjf1qC7wtXU=","id":"530ff9d6-ad60-4bcf-bfbd-214c77a5ab96","last_modified":1575764423465},{"schema":1575764422737,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"R8MQABidwEEcnz5UaEE=","id":"20cbe74b-3fe4-4871-b992-9592f016e6d5","last_modified":1575764423100},{"schema":1575764422366,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"RdPlxJr86INKbkDk2xA=","id":"9e5679e5-6b4b-421a-bd75-15e03c209017","last_modified":1575764422725},{"schema":1575764421998,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABRE8CNrY=","id":"eb4129da-cca8-48d8-b8dc-b4d4ef0a90e3","last_modified":1575764422353},{"schema":1575764421626,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABM6eH/qw=","id":"232533b8-b226-4a59-bf8c-21b0f7c9199a","last_modified":1575764421985},{"schema":1575764421248,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hUtc=","id":"dd4426d9-4d64-4fad-90fa-2774fff02db7","last_modified":1575764421614},{"schema":1575764420869,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGPoA=","id":"53120599-7e6b-41ba-8c6b-d82525a1749e","last_modified":1575764421235},{"schema":1575764420495,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENBIGZvciBBQVRMIC0gU0hBMjU2IC0gRzI=","serialNumber":"RdPlwMK9qnqd94F6tsE=","id":"17a4a929-e971-4b1e-9402-b7644d83d388","last_modified":1575764420856},{"schema":1575764420117,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"GQ==","id":"4dc0a9ae-a508-4b91-a2f8-3c128adcd432","last_modified":1575764420483},{"schema":1575764419744,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"FQ==","id":"c635cb90-ac7d-437f-a7dc-648ec7d434ca","last_modified":1575764420105},{"schema":1575764419373,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"Fw==","id":"40043aba-106e-43ce-9e6e-0a13cae6a921","last_modified":1575764419732},{"schema":1575764419006,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=","serialNumber":"GQ==","id":"37aaea0b-4b99-4995-b895-8254fbbe0cd4","last_modified":1575764419361},{"schema":1575764418632,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=","serialNumber":"FQ==","id":"71f868b0-b192-42d8-a686-e63c8c7a4e3e","last_modified":1575764418993},{"schema":1575747699300,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=","serialNumber":"Fw==","id":"6be93d43-7f5b-46f9-a179-5a2e682f379a","last_modified":1575764418619},{"schema":1572997851534,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2Mg==","serialNumber":"AW0FsQ3o0dDj9mBWCmqb","id":"cf5688ad-8671-4487-aac5-092c069fa6d0","last_modified":1572997851898},{"schema":1572997851167,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDEgRzM=","serialNumber":"ZIiz/9LGv7OdO/Ban8BUUAqNdyM=","id":"da1dc583-9a6f-404a-9387-f20c79a90dd4","last_modified":1572997851522},{"schema":1572997850771,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDEgRzM=","serialNumber":"QPYGU0PATLZx6cglDpDr1Y3YblU=","id":"77c9c8e1-2407-40f4-98a0-aff0f57f5a86","last_modified":1572997851155},{"schema":1572997850402,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"VlTXamae7rQY2vYswRlrObSA6Jk=","id":"1aa8cb43-b425-4bc0-a6a5-4efa70464892","last_modified":1572997850756},{"schema":1572997850033,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/Vsw==","id":"5a6d4421-18f7-4218-98b2-8bf8889c84d6","last_modified":1572997850390},{"schema":1572997849667,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDEgRzM=","serialNumber":"FYi7Goq0FxNJiIxZbyHjnx4Yzj4=","id":"5ce4a32b-7796-4461-ae06-1a674568349c","last_modified":1572997850022},{"schema":1572997849306,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"SUd4pH2sURzNAxRtgemvs0SlWs4=","id":"4981c836-17b0-4a3e-8a35-b69228c35ff2","last_modified":1572997849655},{"schema":1572997848948,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"HZxbikClihb+1PM2ck0SDEZ8/dI=","id":"96ac4980-b6a4-4636-86b7-6e25a51952fe","last_modified":1572997849295},{"schema":1572997848567,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"E4dQDEI92Bh+MVs2aGdlIW8rkDU=","id":"4bb979d3-75b7-4c89-95ce-2f5546a7ac9c","last_modified":1572997848936},{"schema":1572997848205,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDMgRzM=","serialNumber":"Ih46G2P4jpnblyKBdWivHMRTVG0=","id":"a15c4eac-cae6-44c5-9771-a04506e6aa78","last_modified":1572997848555},{"schema":1572997847722,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"aigK80YjKDHJW0LCnSTEqCzDNeM=","id":"8e74eae1-8c6e-4d04-a196-f45bf5fa837a","last_modified":1572997848194},{"schema":1572997847352,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"abLRzPAuINzJXGKJT3+eX1/AV78=","id":"eb428217-5b2d-45e3-a542-8426d8cc97de","last_modified":1572997847710},{"schema":1572997846983,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"IBhwLg4/l5vcFjA30Du20n1cSyI=","id":"533df81c-b06f-489b-8077-22660e1e4637","last_modified":1572997847340},{"schema":1572997846615,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"N1uK21hd0mVD7EMLhwBTDH4Q/Z4=","id":"9bdb8697-2a72-45f8-9e72-9552a8c1cffb","last_modified":1572997846971},{"schema":1572997846251,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"eXbhfvF+r14Z6p4bhGUShI+ougg=","id":"78788abb-6a2a-4ff3-9048-78a304323c50","last_modified":1572997846603},{"schema":1572997845892,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"bj5n4ozUm/ABHHVnnBXHLTgE0d4=","id":"874032b3-094e-463f-84db-4e8093708ded","last_modified":1572997846240},{"schema":1572997845523,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/Vlg==","id":"e71cefb0-abba-4c0c-901e-fdf4a7ce5d3c","last_modified":1572997845880},{"schema":1572997845152,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"aJ22x4QeS1sJqBhO8/15GTsRgkc=","id":"dcd10cf8-d28d-48fc-84eb-c472189c6b79","last_modified":1572997845511},{"schema":1572997844783,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/VlQ==","id":"2a78f5d9-e749-4351-ba1d-4f9af4b597cd","last_modified":1572997845140},{"schema":1572997844424,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/Vnw==","id":"90b1db90-a7a5-4d6f-866e-1df53bc211dc","last_modified":1572997844771},{"schema":1572997843852,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Cik=","id":"d69a8534-6767-4914-829f-951f6ff51629","last_modified":1572997844412},{"schema":1572997843485,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"asr1yYUnTFAnuikoMAbW5MTxWps=","id":"77e343fa-74f6-415b-9976-2e78ace45b29","last_modified":1572997843840},{"schema":1572997843115,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"Fl3SlbNRj/u5Z4ldjyMiig==","id":"731e185c-aac8-49a9-b4e7-6ca1fad82e5e","last_modified":1572997843473},{"schema":1572997842756,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"Z4m9+d/aQi4hDVLz8EBcIg==","id":"6ca403f7-45d0-4a12-bd05-2c32cdc86905","last_modified":1572997843104},{"schema":1572997842393,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAk5MMTAwLgYDVQQKDCdNaW5pc3RlcmllIHZhbiBJbmZyYXN0cnVjdHV1ciBlbiBNaWxpZXUxJDAiBgNVBAMMG01pbkllbk0gT3JnYW5pc2F0aWUgQ0EgLSBHMg==","serialNumber":"Dfp5FitCFjNH/o5ZOoSezg==","id":"f9b36fec-d45c-440d-88f2-d2c36bee2d1f","last_modified":1572997842745},{"schema":1572997842017,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOTA3BgNVBAMMMFN0YWF0IGRlciBOZWRlcmxhbmRlbiBBdXRvbm9tZSBBcHBhcmF0ZW4gQ0EgLSBHMg==","serialNumber":"ATE7Ew==","id":"d9b41fd7-f743-4353-bf99-4beb27bdb962","last_modified":1572997842381},{"schema":1572997841651,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAk5MMTAwLgYDVQQKDCdNaW5pc3RlcmllIHZhbiBJbmZyYXN0cnVjdHV1ciBlbiBNaWxpZXUxKzApBgNVBAMMIk1pbkllbk0gQXV0b25vbWUgQXBwYXJhdGVuIENBIC0gRzI=","serialNumber":"Nfxxz8wMz36ZChR92NTKnw==","id":"d77cda54-e1bc-49da-a0f2-38175d2d1d5c","last_modified":1572997842005},{"schema":1572997841289,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MG4xCzAJBgNVBAYTAk5MMSAwHgYDVQQKDBdNaW5pc3RlcmllIHZhbiBEZWZlbnNpZTE9MDsGA1UEAww0TWluaXN0ZXJpZSB2YW4gRGVmZW5zaWUgQ2VydGlmaWNhdGllIEF1dG9yaXRlaXQgLSBHMg==","serialNumber":"LhEjLBXVlzPRy33vUU/jBQ==","id":"0e4176d5-5815-445f-81f9-6b4edac54c36","last_modified":1572997841639},{"schema":1572997840927,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATE1Sw==","id":"a60a1f5f-94fa-43b0-bc3a-f852c20dfc7a","last_modified":1572997841277},{"schema":1572997840565,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATE3ew==","id":"9d5e3a33-5509-4bff-8b5d-6aeb04494a5c","last_modified":1572997840915},{"schema":1572997840204,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"AeOpMBz8cgY4P5pTHQ==","id":"514984a3-db29-411c-9350-35d6d994a842","last_modified":1572997840554},{"schema":1572997839836,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSMQ==","serialNumber":"bkepyaVT48LOHxRO132s5w==","id":"6f57620c-a646-4b75-9434-6cae78d38d20","last_modified":1572997840191},{"schema":1572997839477,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSMw==","serialNumber":"bkepzLRaKceweNAboyESYQ==","id":"5e742292-83b0-46ab-b2b5-ea22e98fe988","last_modified":1572997839824},{"schema":1572997839109,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSMg==","serialNumber":"bkepys5/hGUZLuczKycnww==","id":"099bfb33-fc5e-4b63-b407-2144887aa248","last_modified":1572997839465},{"schema":1572997838748,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAlVTMSIwIAYDVQQKExlHb29nbGUgVHJ1c3QgU2VydmljZXMgTExDMRQwEgYDVQQDEwtHVFMgUm9vdCBSNA==","serialNumber":"bkepzk9Gwj3iSerMOJRTcw==","id":"fced4db1-a5c4-4f22-82d8-846ad03df6a4","last_modified":1572997839097},{"schema":1572997838380,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"MBKb/YDRk9az4jTk","id":"e51d407f-0292-4711-ad07-8adf26f3b482","last_modified":1572997838736},{"schema":1572997838015,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"AeOugCbbW0HiVsKjUQ==","id":"50850fa6-d0db-43c3-85af-6561d45a52fd","last_modified":1572997838368},{"schema":1572997837654,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"DSNHQZKDDI0wevn963sxJw==","id":"6aaac9fc-8121-4101-8fbb-852f45faa0f1","last_modified":1572997838003},{"schema":1572997837278,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcz","serialNumber":"C2vQOwiS6Py0zO9c8RQ+yw==","id":"e53ccec5-36c3-4972-8418-fb4ec45ba45c","last_modified":1572997837642},{"schema":1572997836922,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UECxMwKGMpIDIwMDggR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzM=","serialNumber":"UoQqGaXHe6Tn5f/4MZM9bQ==","id":"ce154029-f803-4a1f-b0d6-1509d1f68e37","last_modified":1572997837267},{"schema":1572997836561,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJTAjBgNVBAMTHERpZ2lDZXJ0IFRyYW5zaXRpb24gUlNBIFJvb3Q=","serialNumber":"CSBH6lLcNFtGyTwmGjUPtg==","id":"a141c0fe-7121-47bc-8ee0-ce353590daad","last_modified":1572997836910},{"schema":1572997836202,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"DamhD9I49FBVW2Q22Z85pA==","id":"eb820465-1626-4a4f-a084-f33c6e168b26","last_modified":1572997836550},{"schema":1572997835836,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcy","serialNumber":"Dn3kbM04dGYpYMWEN9lNFw==","id":"33a8dd93-74e0-4e52-931b-50d0cb6ce367","last_modified":1572997836189},{"schema":1572997835466,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UECxMwKGMpIDIwMDcgR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzI=","serialNumber":"NWH2OKvBlcu/fP2nA9reyQ==","id":"cb77731b-b0f6-453d-99f5-a734389a8126","last_modified":1572997835824},{"schema":1572997835103,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0E=","serialNumber":"AixZSF45DYuCn2ghjGPEYw==","id":"f0034e6e-0c4f-46d5-a0b8-b3a159ead7f0","last_modified":1572997835454},{"schema":1572997834739,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"QITDXD5mXLU=","id":"f1f0b5e2-88f4-4a2b-b09e-761dea882f74","last_modified":1572997835091},{"schema":1572982913548,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"ALu77u40E1O5","id":"2a9b5e2b-9287-4e06-9385-68a865e9373a","last_modified":1572997834727},{"schema":1568310940897,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2UgU2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjElMCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMw==","serialNumber":"H0ZpvlsmQE2QLTqXSDrK4g==","id":"b7257700-620e-4dd9-9d69-5cb01a38e079","last_modified":1568310941289},{"schema":1568310940486,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2UgU2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjElMCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMg==","serialNumber":"JxLAYQXlXzf2wpMVxAUkPw==","id":"06a25f8a-d351-4d4d-aa77-36d38eaa91a6","last_modified":1568310940884},{"schema":1568310940083,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"APeSt8SBjARY","id":"a2ee1ce4-dee5-48d9-9a6c-7c31abc0cacc","last_modified":1568310940474},{"schema":1568310939648,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"MsKCw6ASAH4=","id":"b87689df-e12f-4a2f-84a8-b62d79ab776a","last_modified":1568310940070},{"schema":1568310939223,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"ALNpo1yEOMIuR5TLwIEiPg==","id":"45196b4f-c18b-4267-bca1-ab2d95a051e1","last_modified":1568310939634},{"schema":1568310938819,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AJHE7Dx8fWBV","id":"3688b8d1-d3a6-4759-a49c-02380f919348","last_modified":1568310939211},{"schema":1568310938420,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"JD4RO0Oolos=","id":"ff8a8a0b-db6e-433b-bfa8-1e7500e3983c","last_modified":1568310938806},{"schema":1568310938009,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxWpuP9VVz","id":"41a21017-a9cb-45ef-99f1-ab1eea6bbe48","last_modified":1568310938407},{"schema":1568310937606,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0Ex","serialNumber":"AQAAOct/vFej","id":"d08d299b-f89d-45a9-94fc-cc7a01a97adc","last_modified":1568310937997},{"schema":1568310937193,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"duIdILCWeCm7g2bzVNjyc3z3hUM=","id":"4b65928e-123d-4cca-ad65-d38064175528","last_modified":1568310937593},{"schema":1568310936785,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHAxCzAJBgNVBAYTAk5MMRcwFQYDVQRhDA5OVFJOTC0zMDIzNzQ1OTEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xJjAkBgNVBAMMHVF1b1ZhZGlzIFF1YWxpZmllZCBXZWIgSUNBIEcx","serialNumber":"DKKQ8bcYDwn4Pows6KhzW6JxMYw=","id":"d218169c-f196-4f86-8f71-60582ba8f4e0","last_modified":1568310937180},{"schema":1568310936383,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"TRRJlNTx8n7cQvNehM76B+mI/gI=","id":"d418fa14-6b51-477e-a854-bb1a8219461a","last_modified":1568310936772},{"schema":1568310935975,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABThOepKci5Vzg=","id":"040501f8-3330-4cf6-81f9-f8718593309b","last_modified":1568310936369},{"schema":1568310935577,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABG","id":"a8c71f16-0d7c-4d1c-ba4a-01047d0dec59","last_modified":1568310935963},{"schema":1568310935182,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5ABI","id":"64f0a9c6-671c-459b-a43e-91ddd5fb76a5","last_modified":1568310935564},{"schema":1568310934783,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"MpyrUqgKLj8=","id":"62e6a159-87ba-4177-9ca1-5d44c11983a9","last_modified":1568310935170},{"schema":1568310934381,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMw==","serialNumber":"cguCxFXg1BY=","id":"a0cfd917-03cd-4a5b-841f-c495ec9e7d08","last_modified":1568310934770},{"schema":1568310933970,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc3Cw==","id":"0b64b385-38c0-4c05-a4e8-33422625cf29","last_modified":1568310934368},{"schema":1568310933543,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDtQ==","id":"1ef257c4-c7dc-4c85-9c96-577da982a917","last_modified":1568310933957},{"schema":1568310933146,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeYsg==","id":"563fcdcc-b8b3-42a0-807a-409f7191aa13","last_modified":1568310933531},{"schema":1568310932725,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfFng==","id":"72344480-7dd6-42c8-94c4-29af6d626430","last_modified":1568310933132},{"schema":1568310932300,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDrQ==","id":"830048f4-fae3-40b4-8cff-ffbde2037783","last_modified":1568310932712},{"schema":1568310931872,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekbw==","id":"18c1a175-78a3-4fab-983c-67f9ef96e903","last_modified":1568310932287},{"schema":1568310931477,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"BkQ=","id":"08a295c5-979f-4e11-ad58-8383c3585b1c","last_modified":1568310931860},{"schema":1568310931080,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"SAOpMdpJPNmCofX5swZ5oQ==","id":"e4d4b36b-eefc-411b-9167-f7793e512b52","last_modified":1568310931464},{"schema":1568310930677,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAklUMRwwGgYDVQQKExNUcnVzdCBJdGFsaWEgUy5wLkEuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSUwIwYDVQQDExxUcnVzdCBJdGFsaWEgQ2xhc3MgMiBDQSAtIEcz","serialNumber":"WuRlPlB5dcPHk+Ni2m98uQ==","id":"8cf5ab64-83b5-4a73-8688-1a057b251bde","last_modified":1568310931067},{"schema":1568310930279,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"ZGOlNeh1j5diJSijGSk5yw==","id":"73e00d24-12f9-4dd1-8f13-0a65385ef608","last_modified":1568310930665},{"schema":1568310929872,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"APx4jVLURBZ4JDuYgssVtA==","id":"e7ca09c8-4234-490d-afa0-5b4e08fa8aba","last_modified":1568310930267},{"schema":1568310929472,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhLUE4gQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEXMBUGA1UEAxMOS1BOIENsYXNzIDIgQ0E=","serialNumber":"BzFJVBKUYLx5d6jqaoqnQA==","id":"ae981d0c-5c32-48eb-8ea1-0df3d2cccee5","last_modified":1568310929859},{"schema":1568310929067,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAk1LMRcwFQYDVQQKEw5LSUJTIEFEIFNrb3BqZTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEWMBQGA1UEAxMNS0lCUyBWZXJiYSBDQQ==","serialNumber":"GWX2i+qVAVmIAm9D6fgusw==","id":"ecb04561-0292-4553-ad7b-46b3d9672be7","last_modified":1568310929459},{"schema":1568310928669,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAk1LMRcwFQYDVQQKEw5LSUJTIEFEIFNrb3BqZTEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEqMCgGA1UEAxMhS2lic1RydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"XtiXZFzoWEohcuXO3Qakfg==","id":"9dff3ebc-a2f7-4a0b-8848-a5fb837b6aa8","last_modified":1568310929054},{"schema":1568310928258,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekbg==","id":"b0f10c1c-321a-4505-b582-9d02f5931519","last_modified":1568310928656},{"schema":1568310927824,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABSOXEhcs=","id":"b9195480-9315-460b-83d6-ac84a68ca9e8","last_modified":1568310928245},{"schema":1568310927420,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAktSMRMwEQYDVQQKEwpLRUNBLCBJbmMuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSIwIAYDVQQDExlDcm9zc0NlcnQgQ2xhc3MgMiBDQSAtIEcz","serialNumber":"H4L5/FnWXnXdXs/8x+BDpw==","id":"6d2b4fdb-b26b-4372-8cdd-b46fb144b987","last_modified":1568310927811},{"schema":1568310927025,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"Ajp1","id":"e0b17c8f-15e4-44a6-ad56-30c577569939","last_modified":1568310927407},{"schema":1568310926625,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UECxMwKGMpIDIwMDggR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzM=","serialNumber":"Bl3KfQ+qIpjDCrBhKUDefQ==","id":"5f65ca3e-3163-4e97-965c-e7e09771652b","last_modified":1568310927013},{"schema":1568310926222,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UECxMwKGMpIDIwMDcgR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzI=","serialNumber":"D4IrRtQ6ByW09Im/6D1i3Q==","id":"42fa7785-9d20-408f-99c9-7bdead71e6f5","last_modified":1568310926613},{"schema":1568310925821,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BwSvmwHgIISTeM4uX8FUyg==","id":"7e94d5de-af8e-4d7a-9e8d-8711bafa9f6b","last_modified":1568310926210},{"schema":1568310925425,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAk1LMRcwFQYDVQQKEw5LSUJTIEFEIFNrb3BqZTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEWMBQGA1UEAxMNS0lCUyBWZXJiYSBDQQ==","serialNumber":"fafwGJHMSPO0K7nm6dSxiA==","id":"b3e2c2e6-8196-49cf-a6dc-2141120f3173","last_modified":1568310925808},{"schema":1568310925018,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNeQ==","id":"79f6982d-ec58-47a8-a0e6-6656ba34898c","last_modified":1568310925412},{"schema":1568310924586,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBHMg==","serialNumber":"BC05mGqcJqxN4m1fywzqdQ==","id":"fb25b1f9-7f4a-4b2c-8287-0500b69ce285","last_modified":1568310925005},{"schema":1568310924187,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBHMg==","serialNumber":"Cx0MvOeigXRY2Z4Uxr0Ypw==","id":"4c4bd6ef-75b4-4822-8c9a-94b4f2c25591","last_modified":1568310924574},{"schema":1568310923780,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBHMg==","serialNumber":"A8Ir2pM+N2ukJUbcpQ9bGA==","id":"cdb14ecd-3eab-487c-af09-568a7061ada8","last_modified":1568310924175},{"schema":1568310923377,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBHMg==","serialNumber":"BiVxMmicX7C3qkZW3rCNuQ==","id":"978c23a3-8253-4a4a-98fb-ce1577248752","last_modified":1568310923768},{"schema":1568310922955,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDrA==","id":"5f215007-f8d7-47d1-a416-4eea3f882168","last_modified":1568310923363},{"schema":1568310922514,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Hw==","id":"e077fd72-0683-4631-afb2-658d83b69cbe","last_modified":1568310922942},{"schema":1568310922110,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"HQ==","id":"2ab14be6-2d83-4d55-b283-bc55bdcb9511","last_modified":1568310922501},{"schema":1568310921707,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Gw==","id":"43a57665-1f18-4c9a-8ed0-9ce125639ce4","last_modified":1568310922097},{"schema":1568310921304,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Hg==","id":"8a038b9b-b34b-43e5-af7c-b33f9dd560a3","last_modified":1568310921694},{"schema":1568310920899,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"Gg==","id":"42002b34-779f-465c-b7f8-7dc081ba9558","last_modified":1568310921290},{"schema":1568310920499,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=","serialNumber":"Gg==","id":"42ef45ee-073b-4069-a61a-0c1fb0186ae3","last_modified":1568310920886},{"schema":1568310920098,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"esKlE8WJEhw=","id":"b718bb4b-c956-4b64-b215-9d1a452892cb","last_modified":1568310920486},{"schema":1568154087410,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"b+PF5BvGM1c=","id":"d1e28ebb-c18a-478f-97a4-2cf4f5e4e78b","last_modified":1568310920085},{"schema":1566360892224,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1569803","who":"wthayer@mozilla.com","why":"MITM root","name":"","created":"2019-08-17T19:57:48Z"},"enabled":true,"issuerName":"MCwxCzAJBgNVBAYTAktaMR0wGwYDVQQDExRRYXpuZXQgVHJ1c3QgTmV0d29yaw==","serialNumber":"PZV/yh+MD8hpLAGZTrVSMQNbnfE=","id":"6f4ad196-1063-4754-a565-7c8a8beef513","last_modified":1566360892591},{"schema":1566360891850,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1572287","who":"wthayer@mozilla.com","why":"registry compromise","name":"","created":"2019-08-17T19:35:20Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"AKmRGsnMtC8mchZkrfEPQvs=","id":"112fbc85-4e1a-4740-978d-a717fd02b1eb","last_modified":1566360892211},{"schema":1566243714956,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1572287","who":"wthayer@mozilla.com","why":"registry compromise","name":"","created":"2019-08-17T19:34:58Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"APoMQ61QytU9iMPwSvd7ZcY=","id":"e172b2a0-7704-4195-8210-22b6c3011640","last_modified":1566360891835},{"schema":1557423813412,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSkwJwYDVQQDEyBXSVNlS2V5IENlcnRpZnlJRCBQb2xpY3kgR0IgQ0EgMQ==","serialNumber":"CYut7lnH+rk=","id":"badf76bb-8e38-4908-905c-7cc1e4183814","last_modified":1557423813772},{"schema":1557423813034,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSkwJwYDVQQDEyBXSVNlS2V5IENlcnRpZnlJRCBQb2xpY3kgR0IgQ0EgMQ==","serialNumber":"WGOh1+g/sGA=","id":"d63543f2-cf39-4f45-a7db-f1ae7c4de703","last_modified":1557423813399},{"schema":1557423812664,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSkwJwYDVQQDEyBXSVNlS2V5IENlcnRpZnlJRCBQb2xpY3kgR0IgQ0EgMQ==","serialNumber":"Ls/8dlIf8aY=","id":"340201c2-23e9-4a8e-87f8-e016599f7982","last_modified":1557423813021},{"schema":1557423812293,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBSb290IEdCIENB","serialNumber":"FQPkzAAAAAAACQ==","id":"863b367b-27a8-4038-94bf-9d2073f23dbb","last_modified":1557423812652},{"schema":1557423811929,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSkwJwYDVQQDEyBXSVNlS2V5IENlcnRpZnlJRCBQb2xpY3kgR0IgQ0EgMQ==","serialNumber":"awVJ9wiyAL4=","id":"95174994-bdcb-4220-b6c2-79e1e1907c8b","last_modified":1557423812279},{"schema":1557423811544,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"IbZ3foy9Dqg=","id":"5ab2bc48-a4f2-492b-8d2c-058829911fa5","last_modified":1557423811915},{"schema":1557423811172,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2UgU2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjElMCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMg==","serialNumber":"Y13XZEprZXM=","id":"5774207d-0be6-47c1-8387-298765987c16","last_modified":1557423811531},{"schema":1557423810787,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2UgU2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjElMCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMw==","serialNumber":"AJCbfptY83jP","id":"e6b04c52-601f-4e00-84c1-c22e842788ec","last_modified":1557423811158},{"schema":1557423810418,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2UgU2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjElMCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMg==","serialNumber":"ANMiAfMpLlCc","id":"c12c5823-b883-4043-8938-0b7076b80cc0","last_modified":1557423810775},{"schema":1557423810044,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARM=","id":"c859b962-72c4-4b7e-985c-a658294cd2dd","last_modified":1557423810404},{"schema":1557423809671,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"JytnIpdF0kOL+XdBhq69","id":"8b701444-ba44-47e5-9bbf-0acc8b34e465","last_modified":1557423810031},{"schema":1557423809286,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE3MDUGA1UEAwwuU1NMLmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQSBSMg==","serialNumber":"KOdv6Js6N0Y=","id":"6d37f8c3-2730-4e2f-a408-cbe1a5db9c22","last_modified":1557423809658},{"schema":1557423808886,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE3MDUGA1UEAwwuU1NMLmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQSBSMg==","serialNumber":"DO4I8+h6DJo=","id":"2c75add5-a852-4f37-ab30-d3aba4474edc","last_modified":1557423809273},{"schema":1557423808512,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtTU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"Yr4AWtEG96k=","id":"a1786ea8-964d-43ff-8034-d92f732d1a8a","last_modified":1557423808874},{"schema":1557423808123,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"YP6Ri0pXsgE=","id":"99218c6d-b76d-4cf4-b759-36881f8ddad2","last_modified":1557423808499},{"schema":1557423807737,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtTU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"OI4Oqw3W3F0=","id":"efda5b9b-146f-4890-be8d-b6ac58b1df1b","last_modified":1557423808110},{"schema":1557423807356,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtTU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"KVbQJstVhmo=","id":"512284c2-8bac-43f3-83b9-6edb4395f99b","last_modified":1557423807724},{"schema":1557423806979,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"d5NjXwLBHrU=","id":"71545b94-9fc0-4513-8959-9e210ee4b90f","last_modified":1557423807343},{"schema":1557423806596,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"CW8YlnNuJhQ=","id":"fe70826c-b167-4421-bcbf-ef1a3c07721e","last_modified":1557423806965},{"schema":1557423806210,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"MiKihpTXxZk=","id":"cbd66b64-8fdc-46f2-8e15-586692a5647b","last_modified":1557423806583},{"schema":1557423805838,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNB","serialNumber":"BcKlTXFc9mE=","id":"c626e9e1-956c-4e87-8ba5-c66eda0b47b8","last_modified":1557423806198},{"schema":1557423805449,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNB","serialNumber":"S4USm53cbIU=","id":"7065ee43-7c3c-4e7f-bf03-0112c648ada7","last_modified":1557423805823},{"schema":1557423804871,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"QAFtPnuRTwc=","id":"abe92cd0-41c3-4dba-a494-d4af228d40de","last_modified":1557423805436},{"schema":1557423804502,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"YgfyfeCfPTU=","id":"d0a3950b-8d10-4cc4-94aa-edb22c99c8b0","last_modified":1557423804858},{"schema":1557423804121,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"G4u0Q4CNE10=","id":"d221d415-8f82-46a9-8c10-a2f86aabf445","last_modified":1557423804489},{"schema":1557423803745,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlNDMSAwHgYDVQQKDBdJbnRlckNsb3VkIFZlbnR1cmVzIEluYzEuMCwGA1UEAwwlSW50ZXJDbG91ZCBWZW50dXJlcyBDQSBmb3IgRVYgU1NMIFJTQQ==","serialNumber":"VfaCotN4OFo=","id":"a5441ef9-557c-43ba-9cb0-54dbd81c2934","last_modified":1557423804106},{"schema":1557423803357,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE3MDUGA1UEAwwuU1NMLmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQSBSMg==","serialNumber":"UqgFJ65x5nU=","id":"d1592e83-6c04-4c20-ba07-56d72f8eb0f1","last_modified":1557423803732},{"schema":1557423802954,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxMjAwBgNVBAMMKVNTTC5jb20gRW50ZXJwcmlzZSBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIx","serialNumber":"T9HiLhDlNNU=","id":"d31f4890-5ce5-4b86-9414-d68b47aa9861","last_modified":1557423803344},{"schema":1557423802580,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHkxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxNTAzBgNVBAMMLFNTTC5jb20gRVYgRW50ZXJwcmlzZSBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIx","serialNumber":"ITFvl6W0i6I=","id":"696f4fd0-6433-43a9-97b9-19b1ee50d529","last_modified":1557423802942},{"schema":1557423802214,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE3MDUGA1UEAwwuU1NMLmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQSBSMg==","serialNumber":"WHsQEmHMXeM=","id":"7299b7c4-27a9-423e-8e37-788987824972","last_modified":1557423802567},{"schema":1557423801848,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"cvzm3dCJNB4=","id":"c91f53c0-d5f6-4a48-af64-92ccb6ee8473","last_modified":1557423802202},{"schema":1557423801470,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRUND","serialNumber":"XlXE8yhjjQI=","id":"65386622-c28f-47ad-b627-b83ea70cc9f0","last_modified":1557423801835},{"schema":1557423801095,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNB","serialNumber":"KMkysqB5Rt0=","id":"dc2fd3db-10b1-413d-94c4-fc4791e7675f","last_modified":1557423801458},{"schema":1557423800730,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJTQzEOMAwGA1UECAwFTWFow6kxETAPBgNVBAcMCFZpY3RvcmlhMSAwHgYDVQQKDBdJbnRlckNsb3VkIFZlbnR1cmVzIEluYzEtMCsGA1UEAwwkSW50ZXJDbG91ZCBFViBTU0wgQ2VydGlmaWNhdGUgQ0EgUlNB","serialNumber":"MMznHIjZYpQ=","id":"1de4a0c1-51d7-47f7-a73d-fd70920f6a34","last_modified":1557423801083},{"schema":1557423800345,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlNDMQ4wDAYDVQQIDAVNYWjDqTERMA8GA1UEBwwIVmljdG9yaWExIDAeBgNVBAoMF0ludGVyQ2xvdWQgVmVudHVyZXMgSW5jMSowKAYDVQQDDCFJbnRlckNsb3VkIFNTTCBDZXJ0aWZpY2F0ZSBDQSBSU0E=","serialNumber":"cTxxiZ4LCOQ=","id":"dcd65990-542f-4ef1-99eb-e2f25e6239b7","last_modified":1557423800717},{"schema":1557423799967,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxMjAwBgNVBAMMKVNTTC5jb20gRW50ZXJwcmlzZSBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIx","serialNumber":"Ti0dlrzCXKM=","id":"ae5978b3-3be3-4707-86ac-6c16d078fe5b","last_modified":1557423800332},{"schema":1557423799592,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCs1Q==","id":"f68dfc42-bb98-48be-987b-192b59c043d5","last_modified":1557423799954},{"schema":1557423799216,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermw5A==","id":"74b4b2a3-32bf-4413-80ae-d470b0375797","last_modified":1557423799579},{"schema":1557423798845,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzM=","serialNumber":"YgZcSJ6iN8fEC7ejOJsdDrm5o1g=","id":"22e259c3-376e-432e-ad1c-774a8988cf96","last_modified":1557423799203},{"schema":1557423798467,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzM=","serialNumber":"Yj9Q2DoRGS8RFsxLEnheErA5ayQ=","id":"29ae1b28-d084-4bc4-a971-732d22ec7b6e","last_modified":1557423798832},{"schema":1557423798089,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"BaYifVmclf61WjM6m2tUE0US22M=","id":"2bff0030-9997-4539-a23d-4c0a85d8b7f2","last_modified":1557423798452},{"schema":1557423797714,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"fSwlctGYM5wOZ6S6SbpfaQoLCUw=","id":"c1c0d933-48d3-40c3-8c22-834c1278e810","last_modified":1557423798076},{"schema":1557423797339,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxJzAlBgNVBAMTHklkZW5UcnVzdCBDb21tZXJjaWFsIFJvb3QgQ0EgMQ==","serialNumber":"QAFmaeynntX5i5Op972mww==","id":"cf97d13a-4b9e-4432-8d02-d1c1ce666e03","last_modified":1557423797701},{"schema":1557423796944,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxJzAlBgNVBAMTHklkZW5UcnVzdCBDb21tZXJjaWFsIFJvb3QgQ0EgMQ==","serialNumber":"QAFqJwTmxn8ekC5jaM8HfA==","id":"5f5cd087-f151-408e-a230-28976be63ce8","last_modified":1557423797326},{"schema":1557423796539,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"CoIvSK+bMR8=","id":"a8275fcc-230f-4da3-b3f9-2b998b34a8ec","last_modified":1557423796916},{"schema":1557423796155,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"CwMSuo/L5Nw=","id":"016ad479-aed7-4229-bbec-3b8a698a744b","last_modified":1557423796527},{"schema":1557423795782,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"BlGKWhgGzQg=","id":"696b55ff-816d-4e13-85d5-e35387da6767","last_modified":1557423796142},{"schema":1557423795405,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"H/Zi2f0Ammc=","id":"cbfd548b-c765-423d-8433-41975a623435","last_modified":1557423795768},{"schema":1557423795027,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"ECuIk98JkK0=","id":"e474c95a-05e4-4a63-9968-dae47f44f7c4","last_modified":1557423795392},{"schema":1557423794655,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"HLxkVswit4o=","id":"4294786a-6fe8-40f4-b20b-6a2b25c681f4","last_modified":1557423795014},{"schema":1557423794271,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"L6vsVC+Y8pqDd1s/rJ5FIA==","id":"1b40a3a7-5ec6-486e-a3fb-6310b2c1dbfd","last_modified":1557423794643},{"schema":1557423793901,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"ATQlK79hz4d80DloGRPBZw==","id":"8b267277-7d4e-41d3-ae64-edd7b5c86ee1","last_modified":1557423794257},{"schema":1557423793529,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"f+Y5UbJ8hTM=","id":"51120bb0-9083-41ed-b17d-dcf7cf06d817","last_modified":1557423793888},{"schema":1557423793128,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFEMEIGA1UEAxM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBFQ0MgUm9vdENBIDIwMTU=","serialNumber":"aS7BLpeXXic=","id":"b0161c6a-ee77-4061-99f2-43c6fda85243","last_modified":1557423793515},{"schema":1557423792744,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGmMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxNQ==","serialNumber":"OikIZKlOYFA=","id":"db1636a2-2737-4628-8bf8-f30a058481d6","last_modified":1557423793115},{"schema":1557423792366,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGmMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxNQ==","serialNumber":"T0gk6O+tlMk=","id":"9a54465a-708d-4d1c-8bf3-4758d39019b0","last_modified":1557423792731},{"schema":1557423791306,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGmMQswCQYDVQQGEwJHUjEPMA0GA1UEBxMGQXRoZW5zMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxNQ==","serialNumber":"L15JXAiBVUc=","id":"7888917e-fadc-4fdb-86b0-f3f44aa27e08","last_modified":1557423792353},{"schema":1557423790929,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ecsPdIBLahQ=","id":"74f5ed52-6ea0-4f9b-bfbd-767a419ef64f","last_modified":1557423791293},{"schema":1557423790556,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"NcGIcro2KS4=","id":"fc3d95a1-e196-4f06-8d95-f3c4701709ad","last_modified":1557423790916},{"schema":1557423790192,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG/MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMTIgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTMwMQYDVQQDEypFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBFQzE=","serialNumber":"cHaafQAAAABR1JZn","id":"22b33327-c482-499d-96fc-e2b3339c9e10","last_modified":1557423790544},{"schema":1557423789806,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"Uc4FAg==","id":"6beb01af-11fe-48f0-ae22-0d00ac1440f0","last_modified":1557423790180},{"schema":1557423789434,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQDEylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMg==","serialNumber":"UdNg7Q==","id":"76694fab-fc61-4f8b-85a5-4a4ee0c3b069","last_modified":1557423789793},{"schema":1557423789066,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG/MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMTIgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTMwMQYDVQQDEypFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBFQzE=","serialNumber":"BFM5+gAAAABR1JIX","id":"7c92ac8b-d796-4ab4-b2ff-bf3b9cd6b8ed","last_modified":1557423789422},{"schema":1557423788677,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwWQWZmaXJtVHJ1c3QgTmV0d29ya2luZw==","serialNumber":"UyCS4eAKFbU=","id":"7d845a2f-7ff3-4199-ac42-9bfbfec8bb51","last_modified":1557423789054},{"schema":1557423788301,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEcMBoGA1UEAwwTQWZmaXJtVHJ1c3QgUHJlbWl1bQ==","serialNumber":"csPGf5ssRXs=","id":"e1788b2b-bb05-4928-b751-b0da7343b062","last_modified":1557423788664},{"schema":1557423786400,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0M=","serialNumber":"CtBCjxRUFHU=","id":"d825f516-fb33-410c-9102-22c7f542b0a1","last_modified":1557423788289},{"schema":1557423786029,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwWQWZmaXJtVHJ1c3QgQ29tbWVyY2lhbA==","serialNumber":"LAfP+WzoaJo=","id":"99e4c959-2076-4273-8bc6-cf447754a3d4","last_modified":1557423786386},{"schema":1557423785649,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQDEylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMg==","serialNumber":"AI8KQNd3KXH0AAAAAFHTksc=","id":"ce729dfc-a683-405d-aa9b-a0307ba3f9df","last_modified":1557423786016},{"schema":1557423785273,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIG+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQDEylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMg==","serialNumber":"UdNg0A==","id":"a3ebf683-2201-4958-9400-068835bf2a73","last_modified":1557423785636},{"schema":1557423784897,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"CkGcaQQF8iUjbrKwr6T69w==","id":"61ad3107-4089-4659-b9a0-4fbd07ff462c","last_modified":1557423785260},{"schema":1557423784508,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"OT3HaBAsXSO1EA749ZVxbg==","id":"688a97d9-9bd1-4fcb-a3f4-6b2a5f877119","last_modified":1557423784883},{"schema":1557423784129,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"ArgkEK/Zm1qPInQleVefMg==","id":"0e822b98-13ea-42f2-9526-5812e92793cd","last_modified":1557423784493},{"schema":1557423783745,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"ZtxTeyP3ul+7qG4Ps6pxYQ==","id":"f116a26d-be81-43bd-9dad-ad748be946ab","last_modified":1557423784116},{"schema":1557423783347,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"CKyPU/WFC2jREm9pSj63yg==","id":"92004088-7b9b-4f30-b095-a2dbcf0f4ef0","last_modified":1557423783732},{"schema":1557423782968,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"bHgAjOXoRfKYXBrnK+DHng==","id":"30941089-e421-428f-b298-579c25569f74","last_modified":1557423783334},{"schema":1557423782593,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"dri/O9LSPOfkoL9YoireCA==","id":"d28b3446-6119-4b3a-971c-42d989ae5dfe","last_modified":1557423782954},{"schema":1557423782216,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFgxEzARBgoJkiaJk/IsZAEZFgNDT00xEzARBgoJkiaJk/IsZAEZFgNBQkIxDDAKBgNVBAoTA0FCQjEeMBwGA1UEAxMVQUJCIEludGVybWVkaWF0ZSBDQSA1","serialNumber":"FCPkDQAAAAAABA==","id":"ebe02656-332e-4df1-9254-099aab288a38","last_modified":1557423782580},{"schema":1557423781840,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"f0J8K+PdFynpy646qUsWpw==","id":"44b30047-2bbd-4483-97cd-11ba40d34830","last_modified":1557423782203},{"schema":1557423781462,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ZasMZAjKdfoGGP8auMEHMg==","id":"2b871e22-453e-4f69-9693-677f79c72767","last_modified":1557423781826},{"schema":1557423781087,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dOKgNVsKclBA1Ajo/4zYOw==","id":"9d2fb829-6906-4279-b25a-42ac52c896e6","last_modified":1557423781450},{"schema":1557423780701,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ZUzcezQWkm8X0uCnEzzoZw==","id":"8e589379-a05b-4a53-8891-337e01835b79","last_modified":1557423781075},{"schema":1557423780317,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"c7UqiCphESsnodANu5EvIA==","id":"e1d493ae-6c0b-4d8b-90b3-43a8a4b527f0","last_modified":1557423780686},{"schema":1557423779945,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"bElJNaCQlbSnDkqEEPkrzQ==","id":"b9de3761-bfd0-4720-ba30-c6c93fd69cdc","last_modified":1557423780304},{"schema":1557423779533,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJOTDEiMCAGA1UEChMZS1BOIENvcnBvcmF0ZSBNYXJrZXQgQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE9MDsGA1UEAxM0S1BOIENvcnBvcmF0ZSBNYXJrZXQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"SYh0NsP2N0/Dxw8T+IJvmw==","id":"feb077f0-6334-4fed-995e-02fd556ab42f","last_modified":1557423779933},{"schema":1557423779157,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJOTDEiMCAGA1UEChMZS1BOIENvcnBvcmF0ZSBNYXJrZXQgQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE9MDsGA1UEAxM0S1BOIENvcnBvcmF0ZSBNYXJrZXQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"c05oq3l3A48UTQMC6xDPmA==","id":"17d8e83c-cd28-4eb2-a657-41424cfb04c7","last_modified":1557423779520},{"schema":1557423778777,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"WGAsRfJbqjpTgxfybB+hRQ==","id":"4e9f0249-f4aa-4752-9618-a71c816a4ec4","last_modified":1557423779143},{"schema":1557423778399,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"BlHrBttW8NGd18BEPdUVSg==","id":"daf1ff08-33e6-493d-b0ba-6bf7ff8510f6","last_modified":1557423778763},{"schema":1557423778021,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"OcFolrgIjwbaL1r7F81ymg==","id":"881e4a9f-da95-465e-a7bf-045e115b74f3","last_modified":1557423778386},{"schema":1557423777634,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"HYwtWO0UsO9eaJk85kvH3w==","id":"278bd7c1-d82d-4578-8ae1-17a1f81db49d","last_modified":1557423778007},{"schema":1557423777259,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHNA==","serialNumber":"HkWAATSKOQL+bu2Kr0Tjsg==","id":"429954c1-ca6a-4dc3-af3e-f166285bcc12","last_modified":1557423777622},{"schema":1557423776878,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"ZajZKYDkNzvlLcysCHjIYg==","id":"08663e30-875e-484c-ae2c-bba329bbbe7a","last_modified":1557423777246},{"schema":1557423776505,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydvrg==","id":"12c94c82-ae15-4f02-9c99-b52a53e018e5","last_modified":1557423776865},{"schema":1557423776126,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeO8A==","id":"a0dd8ab2-8769-426b-97d6-0e97143c61bb","last_modified":1557423776492},{"schema":1557423775747,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHNA==","serialNumber":"Z8ItzUSc94z2xEuisg0j4w==","id":"f8ef406f-9483-4f48-98a1-7aef32ed8dca","last_modified":1557423776113},{"schema":1557423775371,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"M3kpri5YHC6QvsSGsV43Gw==","id":"8f5fbed4-5ce7-4eb2-b226-b610ca5b3024","last_modified":1557423775734},{"schema":1557423774990,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"Jb1BExLrPLdnbYvQdtKm7g==","id":"4f47f19e-d703-4a88-9d44-f5bdfe041e65","last_modified":1557423775358},{"schema":1557423774612,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"a+1Y1DOEid7V14UXFrl5AA==","id":"01af31d0-1545-48e3-b2d8-59dc3152a8ec","last_modified":1557423774977},{"schema":1557423774219,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"bymtvcoxZCxPWB3g+emE5w==","id":"bc4f1c74-469a-441c-a5c1-c6baa44a5866","last_modified":1557423774599},{"schema":1557423773844,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"b+Rtg7qNXBaYW+jVP5TYEw==","id":"bf6c5391-5ea0-4057-b695-9b1fb94ccaa3","last_modified":1557423774204},{"schema":1557423773466,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"FqCOjyfKZi1+9zJ8x/SRyQ==","id":"6bac3e61-4061-4696-bc93-d72f41c5a3c0","last_modified":1557423773829},{"schema":1557423773086,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"B3TduD7dsIRRFuvx6NqUjw==","id":"02a491f6-bf7b-441b-8f13-8213a4a006fe","last_modified":1557423773453},{"schema":1557423772706,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"NyoSnmvYrQid5NSZ0HAKFQ==","id":"47a33daf-2c4f-455d-aa78-8d7094c35313","last_modified":1557423773073},{"schema":1557423772334,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"T413k3/wlSA8EV9AyZKKzg==","id":"0def93c8-5106-45f7-af8c-0f4e0a26c41f","last_modified":1557423772692},{"schema":1557423771961,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhLUE4gQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEXMBUGA1UEAxMOS1BOIENsYXNzIDIgQ0E=","serialNumber":"NgpYt43seMqHJofUSGQM3g==","id":"3bd57f79-2482-4141-89c7-8f9ea9933dee","last_modified":1557423772321},{"schema":1557423771582,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAk1ZMSQwIgYDVQQKExtNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uIEJoZC4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH01TQyBUcnVzdGdhdGUuY29tIENsYXNzIDIgQ0EtRzM=","serialNumber":"RwAisG4tCM7UNFjwHPY+Yw==","id":"9e219ac4-ba0b-4045-bbd2-5b22a9e47d6a","last_modified":1557423771947},{"schema":1557423771035,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAk1ZMSQwIgYDVQQKExtNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uIEJoZC4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH01TQyBUcnVzdGdhdGUuY29tIENsYXNzIDIgQ0EtRzM=","serialNumber":"BeKfxLaKl34S8yFIynon4g==","id":"01b2f9f3-ee15-41a2-9d30-b0380f2db79f","last_modified":1557423771570},{"schema":1557423770337,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeuLw==","id":"8fd446dd-a079-47d3-97a2-f950665b405b","last_modified":1557423771021},{"schema":1557423769641,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEvMC0GA1UEAwwmZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzI=","serialNumber":"APdOGAyZ4nuNn3lPsbfAv0g=","id":"82065756-9ce7-4d71-a1a7-c58330bdecde","last_modified":1557423770324},{"schema":1557423768908,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"FrTxzDM8QlIX94F6bzmmRg==","id":"27d7ce50-fa45-4279-bf44-be6d999c6eb2","last_modified":1557423769626},{"schema":1557423768205,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"FNURHo65qOyqf1vp2eA6Dg==","id":"efb8234d-8502-4875-b668-7592cc057ce8","last_modified":1557423768895},{"schema":1557423767655,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIIBDDELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1BRFJJRDEPMA0GA1UEBwwGTUFEUklEMTowOAYDVQQLDDFzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzMSkwJwYDVQQLDCBDSEFNQkVSUyBPRiBDT01NRVJDRSBST09UIC0gMjAxNjESMBAGA1UEBRMJQTgyNzQzMjg3MRgwFgYDVQRhDA9WQVRFUy1BODI3NDMyODcxGzAZBgNVBAoMEkFDIENBTUVSRklSTUEgUy5BLjEpMCcGA1UEAwwgQ0hBTUJFUlMgT0YgQ09NTUVSQ0UgUk9PVCAtIDIwMTY=","serialNumber":"RUqLEbThNfI=","id":"21aab5cc-3031-4881-b735-d8c95d0a412c","last_modified":1557423768189},{"schema":1557423766965,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIIBCDELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1BRFJJRDEPMA0GA1UEBwwGTUFEUklEMTowOAYDVQQLDDFzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzMScwJQYDVQQLDB5HTE9CQUwgQ0hBTUJFUlNJR04gUk9PVCAtIDIwMTYxEjAQBgNVBAUTCUE4Mjc0MzI4NzEYMBYGA1UEYQwPVkFURVMtQTgyNzQzMjg3MRswGQYDVQQKDBJBQyBDQU1FUkZJUk1BIFMuQS4xJzAlBgNVBAMMHkdMT0JBTCBDSEFNQkVSU0lHTiBST09UIC0gMjAxNg==","serialNumber":"EQhxWldLpE0=","id":"0ad26162-a542-4876-98c6-5468afc3ce62","last_modified":1557423767640},{"schema":1557258110291,"details":{"bug":"","who":"","why":"","name":"","created":""},"enabled":true,"issuerName":"MIGqMQswCQYDVQQGEwJFUzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJtYSBTLkEuMRIwEAYDVQQFEwlBODI3NDMyODcxSzBJBgNVBAcTQk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCBodHRwczovL3d3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTEdMBsGA1UEAxMUQUMgQ2FtZXJmaXJtYSAtIDIwMDk=","serialNumber":"Aw==","id":"d65240be-ff5e-47d9-90ba-93266235feaf","last_modified":1557423766949},{"schema":1554493303242,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1539007","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2019-03-26T04:37:00Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xNDAyBgNVBAMTK0RpZ2lDZXJ0IFNIQTIgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZXJ2ZXIgQ0E=","serialNumber":"BFXgjf2ribj8GNKFDT/8+g==","id":"6ef701b6-5e38-4a9a-b6b9-2c1beed8d2a9","last_modified":1554504516759},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AK8tb0kLM7VzymmWJsfD3A==","id":"d3f0522b-2465-405f-9f7b-60b4855dcffb","last_modified":1552492951595},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AJDvcXc7qWv3KL5T8LZTzg==","id":"bf4d016f-5663-41ab-878f-3125a4ed37d3","last_modified":1547837142956},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"atcGz1KKGVTDnXW50L1A","id":"e247e73f-9f9d-4a95-be21-189451d6547d","last_modified":1547837142641},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"T8WaANEU0o+TGJUhLg2r","id":"59f41045-3213-41e4-a57f-b80f6e718319","last_modified":1547837142322},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AITPqUzKZv4eLCI4WjAAJw==","id":"b77e2e29-365d-47ee-ba09-7737a5c9ead3","last_modified":1547837141991},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDElMCMGA1UEAwwcVUNBIEV4dGVuZGVkIFZhbGlkYXRpb24gUm9vdA==","serialNumber":"WfGaLerthIxK19OQTLUGWg==","id":"40c1362f-3787-4984-a6a5-0990d7e49e37","last_modified":1547837141665},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290","serialNumber":"U3PRzjiR2zDYPa19QJGeCQ==","id":"b2eb4727-dee0-4f6d-a738-e7f7fac9e141","last_modified":1547837141343},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/VqQ==","id":"e38378f4-32d4-4c07-93a5-482380ef4765","last_modified":1547837141021},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzM=","serialNumber":"e41LsLkwucx+Zibwpajkmngu5js=","id":"847dbfce-baf3-4983-a1ee-d88788cbbf14","last_modified":1547837140703},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"T96lTZ6OiZgO5HXc2chfmg==","id":"a07d0ace-fd5c-4c75-a10b-f61f902ba77b","last_modified":1547837140382},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"XLd9GTWYtJqCVi/S1qbPCA==","id":"28365130-2f06-4e4d-8c88-bdb5b67dadb5","last_modified":1547837140050},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dmmZvl03B2fppSvWZ2AhmQ==","id":"70388522-f69e-46af-bad5-030de539f8b8","last_modified":1547837139726},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"T94ltso4x5zl5SmPzGxaRQ==","id":"ff260017-eece-4203-96f7-7fe544eef7ea","last_modified":1547837139403},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ANWeOrGre+B3kYmkmDsQFA==","id":"63ba2af1-3b95-4c2f-86de-8d260c0e7515","last_modified":1547837139075},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"NuO1LvUpC8SX29dTTMDyxg==","id":"4187cbc1-981b-45d8-aabc-55264528b6be","last_modified":1547837138743},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"PLutAhi0cRaKAH2YfGu0ww==","id":"33baf681-54e2-4e2c-a122-c4cd476df1ad","last_modified":1547837138417},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"Aw==","id":"1cefaa15-053b-4ab9-a393-ea6bfcbfd990","last_modified":1547837138096},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"CQ==","id":"04ace127-bc46-4db7-945c-4d0c65c0d526","last_modified":1547837137775},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIIBDDELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1BRFJJRDEPMA0GA1UEBwwGTUFEUklEMTowOAYDVQQLDDFzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzMSkwJwYDVQQLDCBDSEFNQkVSUyBPRiBDT01NRVJDRSBST09UIC0gMjAxNjESMBAGA1UEBRMJQTgyNzQzMjg3MRgwFgYDVQRhDA9WQVRFUy1BODI3NDMyODcxGzAZBgNVBAoMEkFDIENBTUVSRklSTUEgUy5BLjEpMCcGA1UEAwwgQ0hBTUJFUlMgT0YgQ09NTUVSQ0UgUk9PVCAtIDIwMTY=","serialNumber":"GfVBLKRI50c=","id":"6c625a74-448c-4ea8-8a4a-396ea0e9f212","last_modified":1547837137453},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"Cg==","id":"934dba88-38a3-491b-828b-eb3e3c2e793d","last_modified":1547837137131},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"CA==","id":"c2060e12-c016-498e-8f7a-63a84744145c","last_modified":1547837136780},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1521150","who":"","why":"","name":"","created":"2019-01-18T11:45:13Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"BA==","id":"5d203d0c-a393-4007-bf81-e7468b44a3f9","last_modified":1547837136462},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1513609","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-12-14T18:02:57Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTwwOgYDVQQDEzNHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gU0hBMjU2IC0gRzI=","serialNumber":"CpI/GtuuSFspBu4E","id":"3a6ab1f4-89cb-4987-b8b2-54797f88930b","last_modified":1544811398633},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"XtxscvsjagmsjDmthiFt","id":"b476fea3-2cdb-4481-89f0-913db8d7498a","last_modified":1544194317387},{"schema":1552491702967,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AJWE4kFAkUQDWa/pTgHq2w==","id":"236e57d7-b146-4be8-b8d1-29e872612646","last_modified":1544194316803},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"C8qNtOLfRJf1IZuBa5YY","id":"c496b743-29d9-421d-be85-cc3f0fe2129c","last_modified":1544194316153},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxKDAmBgNVBAMTH1N3aXNzU2lnbiBQbGF0aW51bSBSb290IENBIC0gRzM=","serialNumber":"AIDHko+nptD0l30tljroTA==","id":"c7938b05-7beb-446a-98ea-c288e33c6fbb","last_modified":1544194315552},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AKrsBzcrYHp2NTXnbO4+Qg==","id":"8f563a73-5cae-4aa8-b235-482618a31010","last_modified":1544194314942},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxKDAmBgNVBAMTH1N3aXNzU2lnbiBQbGF0aW51bSBSb290IENBIC0gRzM=","serialNumber":"APbjF26Q/6hfA1ECXToQLg==","id":"589ef449-7393-4474-9c3a-643023fb517c","last_modified":1544194314328},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AJpv8fAILOsYJSFFQ2KtPg==","id":"47970400-9add-4b5f-9e45-411f928e4623","last_modified":1544194313711},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5AAf","id":"ab409612-f7ba-430b-bd06-59fdb9a9313b","last_modified":1544194313119},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MIGnMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnk=","serialNumber":"SUEs5AAh","id":"14d8c40f-e1d6-43da-9e12-acbaf631466c","last_modified":1544194312511},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"GPo59VlzNyA=","id":"b0e872b6-06dc-4f2e-8944-ce63aa2eb698","last_modified":1544194311831},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESISaOB3ffRv2jD4gcSgycgm","id":"40de616f-9872-4e5b-9c79-772291fdddf8","last_modified":1544194311237},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESImf/mZpsO94hCWJFJDUDPZ","id":"132dad17-7ebb-482a-bc8a-8b1ab06b6132","last_modified":1544194310607},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAk1LMRcwFQYDVQQKEw5LSUJTIEFEIFNrb3BqZTEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEqMCgGA1UEAxMhS2lic1RydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"CiM0WSw//67JHGWCrlZU4Q==","id":"93d297ac-6894-4a83-8406-0ae2585cf9ee","last_modified":1544194310003},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeHHg==","id":"e3f98761-7fae-4684-bc3b-8c8da50e5ba1","last_modified":1544194309375},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDqg==","id":"2b01f223-8b3a-4da7-8925-44af81bd1279","last_modified":1544194308748},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeuLg==","id":"a0a574cb-2efb-42a7-bc70-51ce91e560db","last_modified":1544194308135},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDtw==","id":"5050d06f-ae56-40f4-8131-5019beeeec79","last_modified":1544194307534},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bfb2Rs8N620oUcAWs41vjA==","id":"d53e3b7e-da21-4cdb-8e68-dacd97d1d079","last_modified":1544194306886},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemYA==","id":"62d36dac-38c1-49d1-b96d-6e018d7a5ef5","last_modified":1544194306284},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAk1LMRcwFQYDVQQKEw5LSUJTIEFEIFNrb3BqZTEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEqMCgGA1UEAxMhS2lic1RydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"UK9vtGRfZt5a3QiUAQUTaQ==","id":"783e58c7-e899-4297-af4e-95d3c6253ce7","last_modified":1544194305696},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFTATBgNVBAMMDENGQ0EgRVYgUk9PVA==","serialNumber":"ZHKPuIaZ7pI39g==","id":"8d006e7e-9f46-4413-909b-52795a0bfff4","last_modified":1544194305082},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFTATBgNVBAMMDENGQ0EgRVYgUk9PVA==","serialNumber":"fs7i7UJNxcrb9w==","id":"e67cb2f1-f829-4659-8823-831d8abb7a46","last_modified":1544194304064},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"KKdkWIX7TIM=","id":"abbc3079-34c6-4101-a577-2db27ca8cbd7","last_modified":1544194302086},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1512640","who":"","why":"","name":"","created":"2018-12-07T09:51:34Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"dyRJDorYkgE=","id":"7e0b53c6-5915-4be1-847b-4c1785fb50e7","last_modified":1544194300987},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484798","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-12-07T14:23:59Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJESzEQMA4GA1UECAwHRGVubWFyazEpMCcGA1UEBwwgaW5kdXN0cmlwYXJrZW4gMjcsIDI3NTAgQmFsbGVydXAxJjAkBgNVBAoMHVNlbm5oZWlzZXIgQ29tbXVuaWNhdGlvbnMgQS9TMQwwCgYDVQQLDANSJkQxFjAUBgNVBAMMDVNlbm5jb21Sb290Q0ExIjAgBgkqhkiG9w0BCQEWE3N1cHBvcnRAc2VubmNvbS5jb20=","serialNumber":"APSjDtifEQeh","id":"188e1d62-6db0-42ec-b603-ff08649962e1","last_modified":1544194300329},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMTAvBgNVBAMMKFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBJbnRlcm1lZGlhaXIgQ0E=","serialNumber":"VAgHVTPgNwAuYo/y/jkd5A==","id":"9cb67873-dc81-4fb2-9e08-ff4aacaf9fb2","last_modified":1541184580803},{"schema":1552492991594,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQQ==","serialNumber":"DDbXyG6tZ+P3+B11YPItUw==","id":"ba22132a-97ca-42f1-a521-87fed171e1b7","last_modified":1541184580485},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ArkguT7SeGHAA9ts1IOWWg==","id":"76e65b53-7470-4e1d-8b75-672633474bc2","last_modified":1541184580122},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfHkg==","id":"b323ad96-398b-4225-aa75-1745251dffcb","last_modified":1541184579802},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeoVA==","id":"ad2f2b7a-3f07-4945-8bf6-ec8606df1a00","last_modified":1541184579472},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQQ==","serialNumber":"CkE6FgBN+nIkANMmgOQkiQ==","id":"de69d003-2a1e-4b76-a367-a4cdc26b2a58","last_modified":1541184579160},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0E=","serialNumber":"DPWCOBgZnlb4K9ZS7Sft6Q==","id":"6c73cf52-b339-421b-8c2d-cb5a6b9f459b","last_modified":1541184578848},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJhg==","id":"9d3e708c-2edc-4ffd-8414-cb9dc0edf46e","last_modified":1541184578526},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNbg==","id":"583b6241-3ab7-4c50-90ea-112bff931a2b","last_modified":1541184578212},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQQ==","serialNumber":"Ajx7/tYZjpFt5dBByJo9JQ==","id":"78be56f6-6b69-42ea-abaa-356d066b3c38","last_modified":1541184577902},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDqw==","id":"6ca65a6d-8aeb-47ae-b6b5-6c24509a73b1","last_modified":1541184577589},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeekQ==","id":"1ea21ad4-2362-45ba-a738-de15afc58297","last_modified":1541184577274},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDtg==","id":"846ddb44-f14a-4712-a1fb-6780e38300b5","last_modified":1541184576961},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"AXscEecDK83Ks/XoEFX8RQ==","id":"33b2de43-06a8-4984-85b5-5808c0baa6fd","last_modified":1541184576649},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd7Zg==","id":"c164ebb8-e020-45c4-ac6b-9bd57b761aa0","last_modified":1541184576330},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RDQTEx","serialNumber":"HQ4ijQIlTBpJKXTUo0geJ5AI4VI=","id":"b7bff651-6a6c-45d9-8bb3-d795ed07bdac","last_modified":1541184576013},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1504300","who":"","why":"","name":"","created":"2018-11-02T11:49:33Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"dMGHU/futOojjYQWtax2Rg==","id":"a9080b65-0185-4097-ab66-3c059b2a04ad","last_modified":1541184575682},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxSDcTuZO2","id":"db09a4fa-41d9-4e6c-b80f-a9be26cc70b2","last_modified":1535652552759},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxSjphH9DY","id":"1179bdb8-27ac-4bba-8e7e-f9c065b0dad4","last_modified":1535652552456},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxTNGDGgYt","id":"5f5530aa-7a1c-4b8f-bc35-1d123477d217","last_modified":1535652552111},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxSxsaAPaT","id":"ac2d20b0-5c89-4575-831a-51ef341f0ebc","last_modified":1535652551805},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxST2Fhyj5","id":"225ca652-d633-46e6-aef2-d97708ea696f","last_modified":1535652551494},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MF0xCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTI=","serialNumber":"IrmxST2Fhyj5","id":"752a5350-9895-434e-abe7-04b85863341e","last_modified":1535652551184},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"Qks10R3Zqs4AAAAAUdNX8Q==","id":"bc1bcbe5-4db7-4a41-8f10-e900f4eee969","last_modified":1535652550869},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfTSg==","id":"06039f5d-19e5-4760-9a27-656f4c949f71","last_modified":1535652550558},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfTSw==","id":"5cddfcfb-2136-4b37-8208-1b0d8dce98c4","last_modified":1535652550249},{"schema":1552492993020,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkg==","id":"1d0f7585-ddb3-44f2-86b5-afacda2fdfdb","last_modified":1535652549936},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeO7w==","id":"6183f199-c1c5-4705-a178-911f35de4916","last_modified":1535652549620},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkA==","id":"424db874-09b3-4a92-8fe6-61c6e10a0c69","last_modified":1535652549313},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeO7g==","id":"e0cb6242-a46f-4c43-a435-0f8550dd1e6a","last_modified":1535652549004},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"W2qOjVqGcY8=","id":"0093c3c1-1c5c-4524-a29b-9d6a857af2d7","last_modified":1535652548629},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"W2qOjVqGcY8=","id":"724dc57b-1305-4bc3-82af-90d7457e08b7","last_modified":1535652548311},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1487485","who":"","why":"","name":"","created":"2018-08-30T11:09:06Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"W2qOjVqGcY8=","id":"aa81cbe1-031c-4e40-b2d1-e6b9ec6abd7e","last_modified":1535652547990},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484798","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-08-29T17:35:07Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQQ==","serialNumber":"CR8HWlsGr6Sdlw/mzOv8gA==","id":"cdd584ce-f3a2-4b7a-927e-1d479586f224","last_modified":1535564772911},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1480853","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-08-29T17:33:12Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJSYXBpZFNTTCBTSEEyNTYgQ0E=","serialNumber":"L41amoCH4B2agSUpD8Wd2A==","id":"8a401bee-cee4-40d8-a61e-903ca0cda17f","last_modified":1535564772595},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1480853","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-08-29T17:32:10Z"},"enabled":true,"issuerName":"MIGWMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE8MDoGA1UEAxMzQ09NT0RPIFJTQSBPcmdhbml6YXRpb24gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB","serialNumber":"AMN6iHtOgy68QBu3kXiaFc8=","id":"514b3b98-0554-4aff-b117-faeafe5f4897","last_modified":1535564772273},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"ANdqi8UFCQChm0RchyjMpjY=","id":"4307675d-416f-4104-b7ca-6d728920cb91","last_modified":1534541096333},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MDcxFDASBgNVBAoMC1RlbGlhU29uZXJhMR8wHQYDVQQDDBZUZWxpYVNvbmVyYSBSb290IENBIHYx","serialNumber":"A3XEm35jzkM3B/8ZhDel7w==","id":"68edcd97-5fc4-40ea-b459-306f4339e987","last_modified":1534541095459},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"AISaJcSkfQq9","id":"7c47f219-cff9-4fef-a855-007eb636ecb4","last_modified":1534541094267},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MEkxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxIzAhBgNVBAMTGlN3aXNzU2lnbiBQbGF0aW51bSBDQSAtIEcy","serialNumber":"SUUmDL8PIBZ0EkIfCV6N","id":"7cc984ca-7513-4e31-bf91-f32799747ef9","last_modified":1534541093107},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"TA7JMQ==","id":"b4858c0b-2060-4327-9a27-0f3ab43765d6","last_modified":1534541092217},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"RWua3A==","id":"fc4c7ef0-5d5e-4a2c-86dc-99f2586d9774","last_modified":1534541091322},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"TA7JGA==","id":"2558efc4-46b1-4769-a57e-f8ac3971ed01","last_modified":1534541090496},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"Beo=","id":"9ff5d4c3-8d66-48ff-9add-343a90b031a6","last_modified":1534541089654},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"U4S9ZGx1FCY3wppgMwTn0Q==","id":"bd9d1022-f109-47a4-84be-ebf91cc901cb","last_modified":1534541088707},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"JMRsU4iZEfeLdmXeFIjy4w==","id":"85acb0b3-8291-4ee5-8137-3147412a22af","last_modified":1534541087581},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"BnG7G8DueagyBXomN87dYA==","id":"cde8301e-94ce-4808-935a-8dc1dc550d1f","last_modified":1534541086654},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"PtgfuDU/40rxF87UP4HpIw==","id":"c2c44bd7-a0d9-48ac-95b7-9b42250f09bb","last_modified":1534541085650},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJCUjEtMCsGA1UEChMkQ2VydGlzaWduIENlcnRpZmljYWRvcmEgRGlnaXRhbCBTLkEuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSIwIAYDVQQDExlDZXJ0aXNpZ24gQ2xhc3MgMiBDQSAtIEcz","serialNumber":"FdJweu3BTeU/YzTvayJksQ==","id":"961d1883-8b9a-4523-8ee5-43ed4ccfc347","last_modified":1534541084620},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"cDosFiyvqdvDoYinOV6PDg==","id":"1c8e5f98-3a13-4f90-9d16-d15580d1c3fe","last_modified":1534541083590},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"LiJxautXUrJeoN4q4RX/Rg==","id":"3cd4e097-6f1d-44e6-9e51-43ca50114727","last_modified":1534541082464},{"schema":1552492994435,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"aqcSP+AsWAmN9xWwAseOqg==","id":"fe1c41a4-4a07-4bfa-b7dc-850433c2e433","last_modified":1534541081450},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByekbQ==","id":"0597bdd4-fb5d-4418-860e-f8e23349c9ff","last_modified":1534541080214},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByekbA==","id":"b797348e-1bfc-4996-be6e-a9f9cb9856cc","last_modified":1534541079187},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"BILpOL1LYav6JuQxlNetFA==","id":"fb097e62-de6b-4b55-afc9-b5102081e107","last_modified":1534541078056},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHNA==","serialNumber":"IW5rxECQ5LEyRGPeZE91ug==","id":"b83dfdc9-8db9-4668-858f-3fb24473e8e0","last_modified":1534541077133},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHNA==","serialNumber":"USISWFWRHGp530VQc2S1/Q==","id":"cb72eb7e-7a95-4a55-9e6f-a0b2286287e6","last_modified":1534541076012},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"I5cyb4y1eoVQS44pO3PAww==","id":"7e42ae24-9a36-4b9c-805e-786c45bd4b2b","last_modified":1534541074363},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAkdSMRMwEQYDVQQKEwpBTFBIQSBCQU5LMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMRswGQYDVQQDExJBTFBIQSBCQU5LIENBIC0gRzI=","serialNumber":"SoA0BJz+EzihvsNlkwlJTg==","id":"18832146-8b40-4eb2-992e-bf066afd87e0","last_modified":1534541073330},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Jje4sy72uF/upHdwh0gBGg==","id":"12d06d11-7118-4d7d-aad8-d6a3a5abf4dc","last_modified":1534541072103},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"e9fp8poJ4jDqpHxVc+7SoA==","id":"c318da0b-ae36-4297-9b3b-54b3704c415a","last_modified":1534541071195},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"H3xY9eXX+IpIl9ixQf3lzQ==","id":"a152bd2e-c4dc-4b8a-9367-68d233e3293d","last_modified":1534541070166},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAkdSMRQwEgYDVQQKEwtBREFDT00gUy5BLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEfMB0GA1UEAxMWQURBQ09NIENsYXNzIDIgQ0EgLSBHNA==","serialNumber":"YfdCZWyRV1sSx5XxyoXKSQ==","id":"5a6a2309-ef7f-4294-a5f5-35713e6b09ef","last_modified":1534541069146},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"SrterKaDHA8hZ+z9gwFXnw==","id":"9a9f2ce5-4adf-44ab-9419-46b2a9c23c0b","last_modified":1534541067931},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"HxapAqDOXuN5BHzREkFFtg==","id":"ccbb9f74-6a49-488f-9a63-d760e364a097","last_modified":1534541066804},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"MyEj11s2KJH0vdnfUfuNIw==","id":"aae675ae-903f-443f-aeb9-b9dbdad319a9","last_modified":1534541065882},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"C95Fob0ttu7S7dIXnjqiBA==","id":"d4aebc29-de67-49a0-ba42-255f38d35437","last_modified":1534541064843},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"A7XRsyidfS8L2dlFuTsfGA==","id":"f5c969f7-ddec-42f6-9ebf-595fbb7c6fca","last_modified":1534541063714},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc3DA==","id":"2bc17daa-0e8d-4d68-bfa4-ba4e68ab506c","last_modified":1534541062617},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByekcA==","id":"5bff7385-6327-424d-9190-6fc5e49e6204","last_modified":1534541061659},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"HvAB3BwhY8g=","id":"95957db4-01f6-458e-9702-b6bac846e794","last_modified":1534541060556},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"ThcGy6zgwpM=","id":"af35a216-5439-4e22-ac65-06b46b10f1e4","last_modified":1534541059412},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"YfJj9o3IPBI=","id":"f5764907-12d4-448f-a9ff-0c7bd49b6e2e","last_modified":1534541058504},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1484351","who":"","why":"","name":"","created":"2018-08-17T22:24:14Z"},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"AahE5mpsDY4=","id":"10e71a2b-68ae-4c3e-aece-21b68e0c9c17","last_modified":1534541057381},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AQ8=","id":"c056f51e-560e-4386-ab51-aa1447c3f778","last_modified":1527680138898},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARA=","id":"7e68e021-3514-4f54-bff4-16562a15fd8b","last_modified":1527680137878},{"schema":1552492995883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARE=","id":"680e1552-a9c7-465b-9230-796fbaae08af","last_modified":1527680136981},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATEz9w==","id":"95d4aa6a-e99d-4706-b071-b6c9d18f38f4","last_modified":1527680136034},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"Q704nTrqxVY=","id":"1507de3d-b758-4803-8048-edaf5b747848","last_modified":1527680135116},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMw==","serialNumber":"SMwb3p7dSlA=","id":"57ec979f-fa95-401a-8791-8adf2edd0223","last_modified":1527680134190},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"XJI7ULS6xv8=","id":"56e35d02-2284-4f72-9dd2-8606c005b3e7","last_modified":1527680133272},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"eNYPiDzOMtQ=","id":"d47cb30c-c61b-4514-9435-14998929b8e1","last_modified":1527680132390},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJOTDEiMCAGA1UEChMZS1BOIENvcnBvcmF0ZSBNYXJrZXQgQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE9MDsGA1UEAxM0S1BOIENvcnBvcmF0ZSBNYXJrZXQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"M9pDPXYgyiimYdML5Wg4zQ==","id":"ce3da6f2-bb52-4ea8-b2ca-334a49f34494","last_modified":1527680131497},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"X407nWyYC7u8lCrBrW2cRA==","id":"3c05d750-a448-4a72-8fe6-337efe7b68f0","last_modified":1527680130603},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"DmbpIZh1fhYcSThCcjaohA==","id":"e3c45873-f60c-4a04-be49-48e84b26c842","last_modified":1527680129682},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"TpTE/3d2UBJYfYHw2LSoww==","id":"4c6efcb4-ab11-4ebc-a527-bb9d4b5d54a9","last_modified":1527680128734},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"W9KDjZvaDeWwN4jQG9TO3w==","id":"4c841dba-55af-4fb2-ac56-9a4e9e090e9d","last_modified":1527680127636},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"RWHsRyzP3KFyjhTLPO4FPA==","id":"49638a65-fc28-4f9f-bac5-618e2c4df184","last_modified":1527680126713},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABECVWTJM=","id":"fafb930f-555d-4185-b11c-51542f67e9ed","last_modified":1527680125794},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABI75RcWk=","id":"cb02a3fb-31a6-4e59-9b7b-298a675dcfaf","last_modified":1527680124869},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABKkKSw14=","id":"ea62e720-34bf-43e3-863a-b920c4f9f3c0","last_modified":1527680123965},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc3Cg==","id":"291cf8ea-ad61-4a25-a829-8444ab7ff3e0","last_modified":1527680123024},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABSOXEgNk=","id":"a2b79aa8-7b05-43f2-8774-33be4e58e12a","last_modified":1527680122103},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkw==","id":"e6b1307d-9179-4d0c-baf0-486fc60f9e3d","last_modified":1527680121187},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"QHdGjRdEcAz+FjRyuIJmog==","id":"e7dd6129-27e9-43c3-832e-465f281653fd","last_modified":1527680120267},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"JekvfVn3h2+OX/V8Ef6vpg==","id":"69975669-0ed8-4c98-8bfe-0179eca26f16","last_modified":1527680119342},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"CHF76YGUdPMMCJ4njfsnwQ==","id":"f09d52b1-8a8b-4ca6-8d3e-aedcdfa2a2a2","last_modified":1527680118421},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"OBGSpfa3Oz6a7zeF/OywMg==","id":"e8d4263a-45aa-4965-b66b-fff4c766fd35","last_modified":1527680117502},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"deh5gFVej9+uQBqlb1fIig==","id":"496ee295-b927-4d33-9fd1-fc87b0327af5","last_modified":1527680116475},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"aKsZrWDpsFlVL0xkShb22A==","id":"79eccf3a-91ef-4238-b579-373bbfc64546","last_modified":1527680115348},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"SFuFrFB7MZnZ6tsqwS47tw==","id":"b52359b1-3f41-4c09-bbfa-8b9e507ec567","last_modified":1527680114428},{"schema":1552492997313,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkQ==","id":"783843ba-bada-4793-af9d-ba731980deb8","last_modified":1527680113504},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byeekg==","id":"d8d6e770-d17f-4d6e-bbd9-e977a8b433d7","last_modified":1527680112688},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekaw==","id":"7726f4b7-43ab-4446-82de-5b94436243ef","last_modified":1527680111761},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpXg==","id":"fe0212f9-fd42-4659-8052-86a4c39e358c","last_modified":1527680110845},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekag==","id":"b86acd44-3dc4-4652-b48d-b0903b1ca74a","last_modified":1527680109917},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpXw==","id":"c8acece6-3bd4-433f-ad93-ac379de4e8d7","last_modified":1527680108997},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"Mi/Y+W40ChdUGpag8vaUjQ==","id":"9f89002a-a395-46a0-b050-e5f32733e807","last_modified":1527680108078},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"eRdKqRQXNv4Vp8qfLP9FiA==","id":"1ad54d87-3100-49f5-8fd1-a156f5a479fd","last_modified":1527680107215},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"EOqAPvgqxt8=","id":"5e5f0c19-5509-4c2d-96d4-7e89771a75ff","last_modified":1527680106336},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"amYSY2usyXU=","id":"0a3b7dd0-23ee-4ec6-8237-ceba9815e4ee","last_modified":1527680105419},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"KZlCQ0XnAo+GY3mKKJoNoNucjT0=","id":"b604fa72-f222-48f6-a8b7-8c7907a5b697","last_modified":1525201514127},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"JJfQeI7SQbQcPQ8Wc4+X2nlpWho=","id":"e5d6417c-1b43-45e0-a9d5-ccad984a9170","last_modified":1525201512695},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"bdheRp0SfvS84GGiPaBnyFhE8EY=","id":"8e9d1e04-962c-4495-89be-f25d3cd7d8d3","last_modified":1525201511157},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Z6RtH7xmDM0r66IKSlpCZNrlRfY=","id":"cc7d8a02-77da-415a-842b-83d2f60e1bf3","last_modified":1525201509729},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"VOQX5SLKeMGyQdoF0X9h38gYrks=","id":"d34174b6-22f9-47b4-af3f-7d78b2ce313f","last_modified":1525201508294},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE7Ow==","id":"6d27a296-13e2-4b53-880e-32f7030708a6","last_modified":1525201506960},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMTAvBgNVBAMMKFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBJbnRlcm1lZGlhaXIgQ0E=","serialNumber":"a5DOAqSUlLm2s6kL0x8gkQ==","id":"04216f09-9d99-4699-bf56-81cb74464d6e","last_modified":1525201505526},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"AeUotGv9K4mpvLzWxw==","id":"ac3d127c-2b79-4a52-94fa-b3ce9f420f2c","last_modified":1525201504399},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"Ro51e1DpnjbH3LKdghY=","id":"e63eb91d-a23d-4f90-babb-9c4c2baf3da0","last_modified":1525201502761},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"R8MQVHZjYD/8LqGrob8=","id":"3264ae57-4d3d-482a-a169-f66652d93ff9","last_modified":1525201501429},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIx","serialNumber":"B6AKfwrKX6H1AAAAAAAAAAE=","id":"7647d289-2123-401d-b316-d84482d851a9","last_modified":1525201500273},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIy","serialNumber":"CMUHBBak0idMAAAAAAAAAAE=","id":"a792f002-d392-4bb5-ac92-94fe71853dbc","last_modified":1525201498941},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"GARMIB0Iaz3xxucE70O9Qg==","id":"dd5c26f0-c931-4d95-ade1-f243ba56a7eb","last_modified":1525201497640},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAktSMRMwEQYDVQQKEwpLRUNBLCBJbmMuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSIwIAYDVQQDExlDcm9zc0NlcnQgQ2xhc3MgMiBDQSAtIEcz","serialNumber":"fLpClvRi4IMKsokzVKT9Yg==","id":"2e3b108e-3455-44e3-b519-262869934aea","last_modified":1525201496208},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"JFcRHv1L89Vu8gagzuR3Pg==","id":"7732cbbc-9821-492e-8f1e-7b8754a1dc12","last_modified":1525201494877},{"schema":1552492998736,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"CAEyq5GePgxvZbmFx5WW6A==","id":"5f6842bc-4062-4445-a442-17ec20539f59","last_modified":1525201493653},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAk1ZMR8wHQYDVQQKExZNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSowKAYDVQQDEyFNU0MgVHJ1c3RnYXRlLmNvbSBDbGFzcyAyIENBIC0gRzI=","serialNumber":"L3UnLdK9iz8XVM1rbm3tTw==","id":"f2d9c522-665c-4d09-b6c2-e0653ca8dc8e","last_modified":1525201492418},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAk1ZMSQwIgYDVQQKExtNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uIEJoZC4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH01TQyBUcnVzdGdhdGUuY29tIENsYXNzIDIgQ0EtRzM=","serialNumber":"Q0dKwXPiEec83XZPgsQh+g==","id":"119dc8cc-5dde-4e71-aa7a-dd2058aaaced","last_modified":1525201490985},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"PpIe9Q1JUVu5nN/+4HWAoA==","id":"b06fa973-e8ef-4deb-8dd6-af1f306563b6","last_modified":1525201489551},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Baw9WIPUcpFvYe8bilTVVQ==","id":"3105cae8-2380-44c9-943b-62bb59978626","last_modified":1525201488149},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"CpSHXk6RnrLSRVVJhVZEWA==","id":"a91e0705-eaae-417a-8cf5-f990c819c96f","last_modified":1525201486895},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"Bxt4PMyN1f5tIXW8W62DhA==","id":"ef5a0861-7a80-4bef-8189-6b190481cd0f","last_modified":1525201485456},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"bcIU/gztAKdw8elgpRh2vA==","id":"451f9b8a-ce9e-4393-866c-2a62440afa7a","last_modified":1525201484131},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"U51Qij2xILJB29u2m4ePyw==","id":"5ae5d4d8-47cd-4519-86f0-9e764f1fd1ec","last_modified":1525201482589},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"VedYmG4aoUcioKT467SDcg==","id":"5c06e662-9307-463e-bdb9-07abfd4f311d","last_modified":1525201481154},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"HkN+3VDzRBFAw/QQ6XZ2gA==","id":"d284e696-c47e-4f9f-97b0-610dc7313438","last_modified":1525201480132},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"XaqJA1pYkpSOSst7Hmcxew==","id":"78487925-3b88-480a-ba6b-1d5e139b1ec9","last_modified":1525201478595},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"cIHLIBl0M9N90NNjZwhwSA==","id":"289275cc-72e5-4d51-b4f1-07346c5e237e","last_modified":1525201477470},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"I+zjm9Bi1ZVKLF0R96thFQ==","id":"efd22973-74ee-4157-8ddf-057a44f23c03","last_modified":1525201475931},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMS0wKwYDVQQKEyRHZXRyb25pY3MgUGlua1JvY2NhZGUgTmVkZXJsYW5kIEIuVi4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxHTAbBgNVBAMTFEdldHJvbmljcyBDbGFzcyAyIENB","serialNumber":"MfSUS8xHwG64IFRIU5IHpw==","id":"9e57aa7e-ff8e-468f-98ed-562dd56eee71","last_modified":1525201474704},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMS0wKwYDVQQKEyRHZXRyb25pY3MgUGlua1JvY2NhZGUgTmVkZXJsYW5kIEIuVi4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxHTAbBgNVBAMTFEdldHJvbmljcyBDbGFzcyAyIENB","serialNumber":"VhmAg9gQ0IaL5+lKzrKYPQ==","id":"a801439e-c1b1-414f-acbb-16b5fe362389","last_modified":1525201473562},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAk5MMRkwFwYDVQQKExBLUE4gVGVsZWNvbSBCLlYuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMSEwHwYDVQQDExhLUE4gVGVsZWNvbSBCLlYuIENBIC0gRzI=","serialNumber":"I1kCCASG38Q8TKOJaqQtvQ==","id":"eca07c7f-1a9c-46f5-a61f-a9696f8bdd7a","last_modified":1525201472349},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAk5MMRkwFwYDVQQKExBLUE4gVGVsZWNvbSBCLlYuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMSEwHwYDVQQDExhLUE4gVGVsZWNvbSBCLlYuIENBIC0gRzI=","serialNumber":"W4sqXNfJgPC3aLKkcOxq9Q==","id":"eac5a645-3936-457a-8d93-f2d8acb71e1f","last_modified":1525201471502},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"F6sWArGVJv7AwBSxbnnqaw==","id":"4a21fbd9-4b39-4d8c-b2c9-82ace310f9c7","last_modified":1525201470403},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"JY5zdgD/mG9A4oB/uzdSwQ==","id":"859ec3d1-70bd-417d-a3a1-bedc847fb4f3","last_modified":1525201469016},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"VBy0L8eIKnVUGpY97OXrkw==","id":"e5ef5cbb-45ad-4ffd-a2db-beb350b195a3","last_modified":1525201468162},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"c+6uFePfrahUGpXs8lhiTw==","id":"b93e70b2-98aa-44d3-a62a-4f3bb49f9966","last_modified":1525201467126},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"PZfTkwQ5Yio+HE2mvtFzDg==","id":"4d559aad-94e9-4240-93d2-054943a9f31a","last_modified":1525201466102},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHpMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxLjAsBgNVBAsTJVNlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8gRUNWLTExNjA0BgNVBAsTLVZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlckNJQy0xICAoYykwMzEhMB8GA1UECxMYR2VuZXJhbGl0YXQgZGUgQ2F0YWx1bnlhMRIwEAYDVQQDEwlFQy1HRU5DQVQ=","serialNumber":"b+8vFPRPzN8+HCEWmIwVNg==","id":"047fdabb-c9a2-4eb1-aaa7-469511a8f1db","last_modified":1525201464668},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIIBGDELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMTQwMgYDVQQHEytQYXNzYXRnZSBkZSBsYSBDb25jZXBjaW8gMTEgMDgwMDggQmFyY2Vsb25hMS4wLAYDVQQLEyVTZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvIEVDVi0yMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJDSUMtMiAoYykwMzEfMB0GA1UECxMWVW5pdmVyc2l0YXRzIGkgUmVjZXJjYTEOMAwGA1UEAxMFRUMtVVI=","serialNumber":"Y3QACu2RGYVJ6FAnJWZpHA==","id":"703b71d5-0bf4-4af5-885b-d5c2165f4062","last_modified":1525201463440},{"schema":1552493000155,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"BqVfPLKBlSg/4Enn+TGdbA==","id":"f4e4fccb-6400-4fca-8557-849ba24afac1","last_modified":1525201462192},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"cEBA0P3KPBk/ojwnYepwzg==","id":"4c13fe3b-275e-4459-bb38-dc54bf6ba01d","last_modified":1525201460880},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"P0qUU7RhznNP6V9iGYbSbA==","id":"4f6b910c-64a4-4919-8ff5-c9fdd1f7d740","last_modified":1525201459447},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"W99Z2UuV5pFP6V8AYIwcVQ==","id":"66226a62-8d11-4442-8cd4-65279cdc08fa","last_modified":1525201458032},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"dfE2CNAy9IxP6VwZ2IU2cA==","id":"e4012675-11d8-4514-ba99-7a519d9f64c8","last_modified":1525201456987},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"IqW4gO46S81PjTpHBA7mUQ==","id":"54088505-0388-44e8-89f3-54dbeee3d2f5","last_modified":1525201455452},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHpMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxLjAsBgNVBAsMJVNlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8gRUNWLTExNjA0BgNVBAsMLVZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlckNJQy0xICAoYykwMzEhMB8GA1UECwwYR2VuZXJhbGl0YXQgZGUgQ2F0YWx1bnlhMRIwEAYDVQQDDAlFQy1HRU5DQVQ=","serialNumber":"On0bAstcoxZP6WERe150Gw==","id":"d2241dbd-e9df-420f-ba92-0c9c9d8d89f6","last_modified":1525201454025},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIIBGDELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMTQwMgYDVQQHEytQYXNzYXRnZSBkZSBsYSBDb25jZXBjaW8gMTEgMDgwMDggQmFyY2Vsb25hMS4wLAYDVQQLEyVTZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvIEVDVi0yMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJDSUMtMiAoYykwMzEfMB0GA1UECxMWVW5pdmVyc2l0YXRzIGkgUmVjZXJjYTEOMAwGA1UEAxMFRUMtVVI=","serialNumber":"JSPC8hAKsUBP6Y3n9JMx8w==","id":"a6240c29-985b-41aa-bfef-a4b5b10c43c4","last_modified":1525201452790},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"L5tOVjVGKtFP6V84tGEFPg==","id":"7780f12e-5f2c-4382-aa26-25e0b06e2a23","last_modified":1525201451667},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"IL094GkEPSU+HAucglL0Ig==","id":"b9db725d-2c89-42ad-8b0b-807311d0a5cb","last_modified":1525201450130},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"KA==","id":"3d04d4fa-8dea-49f3-a47c-71e1443a9136","last_modified":1525201448898},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"UzAV4JqeuGY=","id":"8e357bb0-7738-4fb6-be98-1c3b0f34b883","last_modified":1525201447362},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"bYuYcMtVvjo=","id":"3546a52d-6e2a-4f79-bfda-3c7514eaf39e","last_modified":1525201446066},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"WV2iHxGL6Vg=","id":"7aee1756-65b5-44d6-b368-bf7345dfb4d9","last_modified":1525201444699},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4af5Q==","id":"6d5c851b-0161-406e-8d63-8d3db27ca4f8","last_modified":1521539068414},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4b2Vg==","id":"bfd98186-8469-4f90-9caa-ef94ee7e5793","last_modified":1521539067480},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Hl7MT7aU4GbuanaMzc5eAg==","id":"b5d0f6f8-dc6c-42e6-86e3-db86c0f0ef3e","last_modified":1521539066546},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TrUuR7x7VeU7Qvlwt8Sumw==","id":"cd97a51f-ecd0-4cd0-afac-022a5deae387","last_modified":1521539065613},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ajUDfjuO76YmIt3+fyTLXg==","id":"6562ca7d-c4df-4c31-93b9-4a4ed561f830","last_modified":1521539064682},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"G0UY3ZCa+JfTgAVgvFA8qg==","id":"f31c2c71-e3dc-4f33-a12b-fad7aa9e1b66","last_modified":1521539063753},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dtULH8kD2mThpR/g1YJEtw==","id":"690c5b1d-ff08-4827-b7fe-0b43f8363202","last_modified":1521539062819},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"c5EZjjNc7LMOapbOzjEtJA==","id":"bcd2807e-15df-4eba-be88-2677fd17496e","last_modified":1521539061889},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dn2My7LvPi25AtUw3aPEmQ==","id":"1841b57b-5085-4ffd-9b5a-192ed098c6af","last_modified":1521539060941},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Qk03giZwJwxf5QpixTKflQ==","id":"01c7e0fd-4973-44d4-829a-896db0c7e1dd","last_modified":1521539060008},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"cepjeevcJiJnbGEvdJE1jg==","id":"e27659bd-3699-4eea-afb0-a435dfac9bd1","last_modified":1521539059082},{"schema":1552493001571,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"BtDaTXIs6tBSClhSLPXdYg==","id":"33f91455-1f4c-4fd7-aeea-c7f1df9309fd","last_modified":1521539058135},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ej2u88yEVXEb8BP1K49U6Q==","id":"af65bc77-69b0-4afb-9451-b8ae0bcc7b62","last_modified":1521539057196},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"H/Vx9uatDIulnLLrZjXEKg==","id":"d1b51a6b-bcb0-44d0-830c-394a409c3fa0","last_modified":1521539056260},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"PxYWUib8jdriX5MSGW7Ozw==","id":"b8304b34-1fcb-46bd-ac88-796748e0278f","last_modified":1521539055332},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"T3UrJ2tKvT0lyumu37ic6g==","id":"629d62ec-34c0-466d-b9ec-4f1991f45ac4","last_modified":1521539054393},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"And3HzRA33dI3K772oqBCw==","id":"e7cea443-749b-48c0-90e4-72139c44b9a7","last_modified":1521539053460},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ZpLTr9toPH+XRF7OITitfw==","id":"8e977340-0255-432f-a74f-b45f1d892f59","last_modified":1521539052528},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TpyAwu1JmlIKD9gyf+0d4w==","id":"86c1352b-e5e8-4e7e-9a88-ea8916d08ded","last_modified":1521539051596},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"A09gcxt2IBLNzwqUBAhkDg==","id":"bd99f32d-02fb-4a46-9265-8bdcb343b8f8","last_modified":1521539047661},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dgkExobSurPQq8GYrxxluA==","id":"190e2d0d-35d1-47b4-8b07-73df5c649ba4","last_modified":1521539046709},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"UJ3tpbZLsyrhh60M9CMQaQ==","id":"b4c69adc-2247-4aed-8cb9-e0fd1bd4e457","last_modified":1521539045779},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"MpG5djdbcIoI5TIkJ7vENA==","id":"c2b676e2-f636-4489-ad39-ceadad4d122c","last_modified":1521539044827},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"BlOMLY2hk1OPGflbt/pPXQ==","id":"06096001-fd68-4d0e-be8d-832c24695c75","last_modified":1521539043891},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"APy7Z8kyJRVBcM/oki5xZ2M=","id":"71a73415-ba8f-4281-86b4-76311c2f0410","last_modified":1521539042956},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"ANjIV8rkvmb5E3Wf3aPV2ys=","id":"ca2547dd-66ec-4991-ab40-362581ebdc69","last_modified":1521539042013},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"AKbcLtOIMMwDPSOrzrclZL8=","id":"f463f5b3-b729-4da8-afc0-c54e54d857bc","last_modified":1521539041071},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"BQ==","id":"821bc34c-45ce-444a-b7c0-0a581a788a52","last_modified":1521539040133},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"Ag==","id":"490cb9c4-e092-4200-9e4b-be790d4db9b6","last_modified":1521539039175},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1436524","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-02-13T20:30:40Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMSAwHgYDVQQDExd0aGF3dGUgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"dqN9ZZM/PfFCXStajJdbtQ==","id":"1dea3a27-cf12-440c-b77d-08608dcb4fae","last_modified":1518553957211},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"IsWDgJMv7uY=","id":"6252eb0e-d613-4290-a7ab-1b6698146077","last_modified":1518185155027},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"WDFms0iypljMkohTzBvf4GmTOu0=","id":"938ea097-b56a-4286-9370-a1dabb46c908","last_modified":1518185154165},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzM=","serialNumber":"PybG62jqpxKYOV5MlXAGPJYDy9M=","id":"495b31a1-84f2-4a2e-b4b0-f24303c0b114","last_modified":1518185153363},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SsQ==","id":"5373d63b-fdb3-4cf2-82c4-6d5dde47a536","last_modified":1518185152542},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATEzEQ==","id":"e0589829-384d-4cd8-952f-3b4d5b3116f0","last_modified":1518185151698},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE33w==","id":"b4208886-7ca1-4d3f-a6b7-271f93aaf6cd","last_modified":1518185150862},{"schema":1552493002970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byecpw==","id":"0a419007-294d-4c7e-8ae4-e26c83633f5a","last_modified":1518185150011},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHoxCzAJBgNVBAYTAkFVMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazErMCkGA1UEAxMiU3ltYW50ZWMgQXVzdHJhbGlhIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"MZNwCx0BAjzTOgcvHsmdhQ==","id":"f7ee0207-7809-4310-a334-906a783c94f9","last_modified":1518185149162},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"PWwhjEHh0n5G6P8b+bAkcg==","id":"8ed4a6a5-4222-44bd-b52a-2fc5b2093fd4","last_modified":1518185148285},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye/xA==","id":"49f10bd9-4827-42f8-b6bb-1136cdb8b1f1","last_modified":1518185147458},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkFVMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEmMCQGA1UEAxMdU3ltYW50ZWMgQXVzdHJhbGlhIENsYXNzIDIgQ0E=","serialNumber":"Nn6RHaVImMEtHLbPqlyGEA==","id":"49216c75-cdfa-423a-84cb-a4285e9efc65","last_modified":1518185146632},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"X22XOlwfc1Taw/ORwGOIeg==","id":"21e8b448-bdc3-4549-8436-7b5218662f7b","last_modified":1518185145800},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"PgImeGqCkapG6P426Ne85w==","id":"9c7330f0-ac62-44f6-9ecc-1f6c8090e22c","last_modified":1518185144953},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1433118","who":"jc@mozilla.com","why":"key compromise","name":"","created":"2018-01-30T17:48:22Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSkwJwYDVQQDEyBDZXJ0dW0gRG9tYWluIFZhbGlkYXRpb24gQ0EgU0hBMg==","serialNumber":"VEav0UR+l38TpKTRi7sS1g==","id":"cb712a6d-3b3d-4642-b0f0-5f765f615559","last_modified":1517334651604},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye9zg==","id":"fead3048-84a5-4256-9850-cf412c8cce88","last_modified":1516714883099},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeWyA==","id":"5d178546-44d0-4756-8bc1-aa84c958ec6d","last_modified":1516714882194},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye9zw==","id":"ce6dc2f0-5709-49d6-a762-87e297e2c4f3","last_modified":1516714881354},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1427034","who":"mgoodwin@mozilla.com","why":"","name":"key compromise","created":"2018-01-17T13:03:45.551668672Z"},"enabled":true,"issuerName":"MHAxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xLzAtBgNVBAMTJkRpZ2lDZXJ0IFNIQTIgSGlnaCBBc3N1cmFuY2UgU2VydmVyIENB","serialNumber":"Cn+uUpLudsH09lYYIPTK5A==","id":"37450b9d-89e2-4144-af21-c01dfb50d5e8","last_modified":1516714880459},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430498","who":"jc@mozilla.com","why":"","name":"registry problem","created":"2018-01-17T00:30:37.551668672Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"AJk3QFH13eHUHHVnsvwS0Vo=","id":"c3485d18-5309-46f4-a324-b72aae76d2fa","last_modified":1516150019120},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430498","who":"jc@mozilla.com","why":"","name":"registry problem - remove after Feb 2018","created":"2018-01-16T14:26:03.648712626Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"NlLRZJFLco/An3cLAGjGgQ==","id":"ee550d4f-2e5e-4a92-84a0-97595775682d","last_modified":1516119227966},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430172","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:24:38.732932137Z"},"enabled":true,"issuerName":"MIGSMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE4MDYGA1UEAxMvQ09NT0RPIFJTQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0E=","serialNumber":"TasC8Zd8BT8kXEE67cFQmA==","id":"fd5a2c90-20dc-49fa-8d98-4ce4f75a9e67","last_modified":1515779270416},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1425376","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:10:12.532698105Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"UDE/uwr4z5V8eZI4+1gkAw==","id":"c848badb-926d-4a4b-84ca-776d8e83afbd","last_modified":1515773559723},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429636","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:07:30.989396006Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExGjAYBgNVBAoTEUludGVsIENvcnBvcmF0aW9uMSUwIwYDVQQDExxJbnRlbCBFeHRlcm5hbCBJc3N1aW5nIENBIDZC","serialNumber":"HwAABsvzDP+DIzUG6QAAAAAGyw==","id":"754959ef-52da-40c2-9f01-6d58cee4bb6e","last_modified":1515773559394},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"bqapwACCtKhVagTl7cEP7KFbM0E=","id":"557dce95-1f9d-4292-b0e3-1e6190ceb6b2","last_modified":1515506204155},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"BFA=","id":"8b5b2498-3bda-404a-b778-8231f31548ed","last_modified":1515506203323},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNbw==","id":"54bc1bfd-3c57-4698-9702-bf18862330e5","last_modified":1515506202308},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"Eg==","id":"bc46d429-2528-4068-b205-b0f853e3865b","last_modified":1515506201306},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1425166","who":"jc@mozilla.com","why":".","name":"key compromise","created":"2017-12-14T17:17:08.723413Z"},"enabled":true,"issuerName":"MIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcy","serialNumber":"AOfHzdPzlvw5","id":"47a94296-eb80-4f80-a327-d6c0dcf96e83","last_modified":1513273512012},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423400","who":"mgoodwin","why":"Added per CA request","name":"Microsoft IT SSL SHA2 revocation 2","created":"2017-12-06T16:51:03Z"},"enabled":true,"issuerName":"MIGLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMRUwEwYDVQQLEwxNaWNyb3NvZnQgSVQxHjAcBgNVBAMTFU1pY3Jvc29mdCBJVCBTU0wgU0hBMg==","serialNumber":"WgAFElbyxxPA8BdM4gABAAUSVg==","id":"41d101d3-2258-4c62-94b4-288e140a4205","last_modified":1512596195433},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423400","who":"mgoodwin","why":"Added per CA request","name":"Microsoft IT SSL SHA2 revocation 1","created":"2017-12-06T16:51:03Z"},"enabled":true,"issuerName":"MIGLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMRUwEwYDVQQLEwxNaWNyb3NvZnQgSVQxHjAcBgNVBAMTFU1pY3Jvc29mdCBJVCBTU0wgU0hBMg==","serialNumber":"WgAFElcDxFjoswSzjAABAAUSVw==","id":"d6e37caf-2691-4a82-8682-72b454419d8c","last_modified":1512596194454},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"em/HTY01Cvv6ITgkH+ftlg==","id":"7b48e485-3f00-4838-98d7-78c731f014e7","last_modified":1512488574225},{"schema":1552493004389,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"a2GKnRbYMZ0oZkRzJE8NIw==","id":"0efe9970-3656-4aa9-8fd2-cfe290ca2c7e","last_modified":1512488573423},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"QspbHxzWb41SX9TUhF1N1A==","id":"bb2d8dfc-6dd0-47c3-a46c-c0f8235418a4","last_modified":1512488572398},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"PbXdgANzAyCOCZ5qa/7E6A==","id":"f3f7d94c-c3d6-48f1-b807-43c97784dcdc","last_modified":1512488571476},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EgtJ1f+/tZwlGfg0Uu7XCQ==","id":"331b24c7-b0dd-4289-9ef7-a4f92eb4f449","last_modified":1512488570451},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"TbPyD9NnsEcxyK6LIsr78g==","id":"eb7bda20-89d0-4ed5-a731-0896127de01e","last_modified":1512488569530},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"JjjcXrfGjTCi1ug/AEeYlg==","id":"0f7d3bf7-ddeb-4c1b-ba24-7ae9157bba15","last_modified":1512488568584},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"HGD2RtvXMaPDqHIPLdXocw==","id":"b26128cc-3096-438e-858f-7c2cbaf3c903","last_modified":1512488567585},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"fa9agGguMHfBorMTXXMd9g==","id":"2ace54b8-3856-4aa9-bd26-45f573e737ce","last_modified":1512488566638},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"WfPUsnnSF04ShWVYEa/KRA==","id":"5bc1d739-7788-4f13-b92c-5b6a8662319b","last_modified":1512488565741},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"LzVYePklc3vH3jkk0BZr9g==","id":"bc7eea97-3ee7-49a0-80a7-c0f1a346a1c4","last_modified":1512488564721},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"BWuckD4dPHZYW5ThBsl+aQ==","id":"2a474462-256d-4583-9103-297077b85bad","last_modified":1512488563751},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"LJ8wKbrQXgT8VExZ6vEfWA==","id":"4a1c1053-a8a9-42ff-bb3e-3ac5c536d5c3","last_modified":1512488562853},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"GskXrIFkzLS+4yohQM9EUA==","id":"a3b8a885-9d36-483c-8b4c-c80e8795bb92","last_modified":1512488561945},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"X3iUdzxCEtOAKpiTLsqjBA==","id":"7fc162c0-b668-4336-ad9a-cf6ac4bf7f88","last_modified":1512488560934},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"UKM/CNF2OvC4giYnAUG/Ag==","id":"7f8575f4-dcd7-4e51-9540-674ea52a0afc","last_modified":1512488559917},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"fZ10MyCe51jAjZCsDgqaxA==","id":"a943a2dc-e783-4560-90ec-5b2ce4936f60","last_modified":1512488558952},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"Gz4uHrL2usrTZrPCHeuF5g==","id":"cf84a41a-afeb-4727-b51e-f1489075f5a0","last_modified":1512488557959},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"bf8hEJywo1lAp4UNcLl5Ew==","id":"26c0ae81-c15c-4f37-930c-f3c39fca709a","last_modified":1512488557038},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"P4sUnc++hlU/bXj0zSTlcQ==","id":"1a68fa22-b801-4f56-81b2-a6575dd928ac","last_modified":1512488556115},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KUZMXOUj2sdY2i2Rfgp/5Q==","id":"4c1f25cc-e17b-4ce4-a0c8-ab871a370238","last_modified":1512488555092},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"a9HDb1beqQYmkvFH0qExcg==","id":"b876cede-af38-44ff-952b-cf1652e0eff4","last_modified":1512488554136},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"C2tQZWb2eoQD2XC3F5JSzg==","id":"67c163b1-7be2-434d-9a17-24ab282e0906","last_modified":1512488553221},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"QjiuX0y1agXQQqmDB2yh3w==","id":"966bf4c9-229d-40ea-8783-cdd20a90e7d0","last_modified":1512488552326},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"YwslVqGwc9CHkaZkXNZ4xw==","id":"e35a9cd7-72a9-44b6-bb42-c43054e279d3","last_modified":1512488551279},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KRfQOuBdOSpEmAxSpDZGZg==","id":"3901e046-eee7-462e-9207-62a2074d5555","last_modified":1512488550258},{"schema":1552493005810,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"IARKrBjlKQLyVGA4X52L7w==","id":"59872bbc-66b1-4627-890b-b8e9aee46d08","last_modified":1512488549244},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"TsaDDThhoyhX10SURO3NMg==","id":"477a1238-b526-4dbf-9e7d-8807315f8e5a","last_modified":1512488548206},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"dSBsq/te0hzZauKHgJ3EWg==","id":"320c2435-4a3d-4a9c-898e-0be3e7314601","last_modified":1512488547208},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"JLLEdDl2iHqqyenVWwQ/XA==","id":"d1d33ccd-4ea7-4b1f-9969-b77036da72c0","last_modified":1512488546183},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"D4dSwi4udjGtMftKLTSFyg==","id":"36e0661b-bbce-412d-b181-f51599b5133f","last_modified":1512488545212},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltmw=","id":"7ab02aa8-9300-4e05-bd35-1a8a0dc66114","last_modified":1512488544217},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm8=","id":"3128a9a7-5929-495d-b6e9-d1322d8969cc","last_modified":1512488543316},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"N4XreFRrqFQ=","id":"0cf09345-c803-4248-8e8f-4fd437efc225","last_modified":1512488542191},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"Ah69dEvrzT4=","id":"eabda172-8673-4d9d-b955-ae33491273d0","last_modified":1512488541251},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"RXJFI0h6EJY=","id":"0ac03d6a-f013-45f1-a611-8d408d81cda2","last_modified":1512488540265},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"DA==","id":"8374c965-72aa-4411-96a9-d0ed94b6eff5","last_modified":1512488539210},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"AklaZYwhC9k=","id":"0ef6e97e-f104-472f-a639-f5095bee2cec","last_modified":1512488538203},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGcMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0x","serialNumber":"APB/jQRgyP8Q","id":"89031d16-d554-432c-b874-29611e57ddc7","last_modified":1511530774264},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"AOVojQRgyPcY","id":"365afa37-c1b7-49a1-b426-3ad6f41062ce","last_modified":1511530773342},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTI=","serialNumber":"APB/jQRgyPca","id":"469dc3f7-856e-46e9-bcd4-4690669a1164","last_modified":1511530772420},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"AOVojQRgyPca","id":"350ab323-afb6-4b13-ad9d-4fd751b43b6d","last_modified":1511530771603},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"OeKv0wi+ATDxfQ6CWir1vA==","id":"f9cdfe8d-8646-4f51-a52e-2f8e207dd9af","last_modified":1511530770270},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"VNb2Hjai/t7dmCtOzRXXew==","id":"58ff4957-a4c8-490b-8ed2-28ec1730c0e5","last_modified":1511530769350},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"CuUEKEJM4xhxlFXraPcSpQ==","id":"7601c888-8cc4-4c4a-a1f8-c7035f722d59","last_modified":1511530768331},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"FK+rVRFA0o0PnW+X6V60gQ==","id":"94b0d239-ef85-46fd-8af6-4213e19bbe5a","last_modified":1511530767405},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"UT6GtTGbEC6SXJteWAKy2g==","id":"f232a4f0-ab91-4cde-acd6-28745c3c2bd0","last_modified":1511530766483},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"c0ENPRDbRozjU83garZrdA==","id":"5c07893e-ed64-43c5-aabb-fd7d059100f6","last_modified":1511530765531},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"ODTGURr0vY14WkIt15hHrg==","id":"26b8bba0-1be3-4f66-98d3-936a13c810b8","last_modified":1511530764744},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"RkNUwM80Jt7beb4ek+iI8w==","id":"e28af90b-6ca1-4335-876b-4afedaea6cf8","last_modified":1511530763884},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"dUIqmrcgq/261bRbo7fM1g==","id":"6d8170da-8177-4e04-988b-e24f36c39001","last_modified":1511530762701},{"schema":1552493007210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"XbPH0u4MjoIrWzN8QCilfg==","id":"a44b3f08-cbb8-4fbe-98c0-e7710dd3e81e","last_modified":1511530761466},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KvQ5AzK6tQy8eBy7NAD/lQ==","id":"882fa317-43a7-4515-b79b-437119b72cf3","last_modified":1511530760452},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"UfM8pWkcmmLGRiGIVydmoA==","id":"069856d2-6bd0-4b39-a8f5-2debd4535542","last_modified":1511530759416},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"X4C5SJIG0BDeJvpQq4ngCw==","id":"9abf8a9e-66d2-4193-9dd8-3d86f482d44f","last_modified":1511530758551},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"CGo/+42e75JBJ2JcOEaMFw==","id":"879c2baf-c634-45eb-b80b-c1fb0ceb31d9","last_modified":1511530757370},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"Q1r0dRkkG9miuHj/Y52izw==","id":"9e9ecf02-4c1c-4c32-b10a-c7272c416b5f","last_modified":1511530756553},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"WU+jmMhGAumhewqVKrZBmg==","id":"27bf3c0e-8868-4274-b37c-b3a4bde99ba1","last_modified":1511530755428},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"d8ToN4Dfs5RqD2yfAp12yQ==","id":"972f597f-5333-4ec4-8801-751bb5546abe","last_modified":1511530754297},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"ElBUYv/f+6+gnbAJ23qnAA==","id":"6ad92631-7061-4717-93ed-b5f56d8452b1","last_modified":1511530753374},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"DoP7aSdEs/3y+o2Gj9zgWA==","id":"16737b7d-6e89-43d1-8a4a-0f1a931371f8","last_modified":1511530752482},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"XOZMbPKQuJEw8Ib5neDVpQ==","id":"6d117cdb-5081-48b0-8408-4ca74edb943e","last_modified":1511530751226},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"UN78HLEKf7W9vQYkzYpJnw==","id":"e52276ca-6055-4069-8277-e046a6c8dca1","last_modified":1511530750302},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"KNhgX8XuJduYciIyatpOQg==","id":"000e9e4e-75dd-46f1-8acc-acdb9844a1ba","last_modified":1511530749075},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"OIJdAvYxHmLb6YaaMmwmjg==","id":"b2085d97-60ab-449c-ad46-8ca2818da916","last_modified":1511530747846},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"SrQ125q7UcLfxVKepx+lRg==","id":"5b2d0011-e159-4fe2-8d40-72fd5c210474","last_modified":1511530746840},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EYfoVrySx7V3OUqs4xKvgA==","id":"39bf9bb4-2301-4d71-8c46-7a88f5b0cbae","last_modified":1511530745816},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EkoaKijVTGVYI5c604iweg==","id":"eb900242-3154-40c3-8f90-391c5c15a6d5","last_modified":1511530744778},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"VIFPnH3Io2OmF0J5KK8gzA==","id":"0aa3a176-7080-48d4-b8f2-8a3c60a6de88","last_modified":1511530743731},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"ANsAyDuSSs7Z83LfMZ+TDw==","id":"f20c25eb-a06f-43ac-a202-710565679819","last_modified":1511530742622},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIQ8dLGqNIaxxMeg31W16Q==","id":"aec665a0-9d68-4342-9743-18efc713e0f8","last_modified":1511530741394},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIQ8dLGqNIaxxMeg31W16Q==","id":"8a10108d-b91c-49da-9748-72421d965126","last_modified":1511530740428},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"cFbYT3bxd1sAAAAAUdNX8A==","id":"892f7600-cbf9-41d7-8854-91e39cca6d64","last_modified":1511530739059},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DNHqTQd9QC+JnMy6AWyhkg==","id":"8f08f0c9-78a0-46cf-ac37-4d272b696046","last_modified":1511530738030},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-02T22:09:46Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AxPlMqxkByCn3XNuYMhYNMcp","id":"eab2fa01-c3d4-4fd1-b3b8-9d88ed9b6657","last_modified":1509980661621},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723413Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BPVqx4UbKVAbJSFTKwrcFryU","id":"f644b647-a845-40ef-9f6c-36744f304d08","last_modified":1509744817871},{"schema":1552493008615,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723410Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOncXh7IZp1SNydhtUdyh2O2","id":"58e3d1dd-4602-4b04-9f99-3f6efe1b0653","last_modified":1509744808464},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723407Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOc11keA9WJ9R20XQY8hO7yi","id":"749a02fe-2f0d-4eeb-84ff-f2730ec10bdf","last_modified":1509744807487},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723405Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOPwjyn5eqfeoxs7Z0y3vqNN","id":"9bcd94b9-c798-43da-9520-f15ffd3418e8","last_modified":1509744806955},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723402Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BONHqLIx/ibQE08IQIyoGaXg","id":"1b719105-db02-4597-8d5e-4e60a72167dc","last_modified":1509744802604},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723398Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOIIipysxAz5xHIMmFRvYchY","id":"6f43ef92-37ea-407d-b113-0d1a2f30af6d","last_modified":1509744793918},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723395Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BLlQHJ611eOZuedFrFgVAfAs","id":"af6370dc-0ee2-4f46-864b-4aba6dad16aa","last_modified":1509744793363},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723392Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BKrxi2/1iFxHEFzyZvegxq5C","id":"8636eb93-74a1-4a6a-9fbe-c027fce6e1f3","last_modified":1509744792878},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723390Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BKobzjrOxa/6kCR0ImKoqaQW","id":"87cdeef4-a32f-4f89-90b2-d979766f66fd","last_modified":1509744792287},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723387Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BJDHnthjoDRutxFRJPFnixbU","id":"fd062b35-a923-4f40-adb6-b438b21dcebb","last_modified":1509744791739},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723385Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BHT6CK6B569m/dd5dEluBOEd","id":"dbd760d1-545a-4c22-9634-8266b173fea7","last_modified":1509744791182},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723382Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BDV89QWZE9MJYlCpFQUv5Y2W","id":"5933c583-8b53-41b9-a23d-3fa849a39f22","last_modified":1509744790658},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723376Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A/99bZCzSpexYL5y6dSryDn3","id":"62a22818-bb50-4f99-ae28-194943003e28","last_modified":1509744790097},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723373Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A/7DHCczBnP5qUVh0jF2pvwB","id":"930fdbad-652c-445a-be30-1721420d5308","last_modified":1509744789472},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723371Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A+ly3y1rVP59k/MKfcE3DoEq","id":"2be75058-2815-46b4-97de-5f800fac23fb","last_modified":1509744776797},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723368Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A+RCQYwhofmXM+/hxdyoUzkI","id":"ece94a68-9224-462d-aa7d-174e461c3eac","last_modified":1509744776283},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723366Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A9BRwOwbXRRhCe+kcmglgW3z","id":"b17c537a-31c2-4547-90a7-5588e967e0d2","last_modified":1509744775761},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723363Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8wZnhfuY6VIV1SwGsTGNR7L","id":"06dd2b87-9f23-4ecf-a6d7-1c4e248c377d","last_modified":1509744775215},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723361Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8aDg1/IA4O8gjMPZHVqPI+w","id":"e90d77e0-1e41-4a45-9c4b-a0b615b0091d","last_modified":1509744774659},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723358Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8LV4zckxcwdttbQSk0EPnoA","id":"421f4d83-9377-403a-b28b-c7249634e7fc","last_modified":1509744774150},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723356Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7uy+rmTav6tDH4dRrsnvXGH","id":"188d1c6c-c94c-4a1a-8028-cbc7c29069d4","last_modified":1509744773593},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723353Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7T0V6o47rgCKl3oUb7jF2Ph","id":"fee8894c-8624-41fc-ae9a-7180f52714f1","last_modified":1509744773026},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723350Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7RCxMe1S9Hb7ENzRxl0mxGP","id":"fca062d6-5292-4ca1-87ce-a6aa34c6a1ae","last_modified":1509744772514},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723348Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7GX+szdK8/7Kf0xUuarfyIN","id":"fcaebe3c-564b-46c0-a852-a6e51d8a56cf","last_modified":1509744771973},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723345Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A5oET6WBWx72ColKf0txoWyR","id":"b6cd6dd6-4173-4584-ad06-d3a6400f4c4c","last_modified":1509744771414},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723342Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3ZQibPGSZ8nPVbuccaCvUfa","id":"c67ca525-ccdb-4ef9-8029-422656cbdbc8","last_modified":1509744766044},{"schema":1552493010014,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723340Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3WVy2V+2VFkWtMvA6HFwnhq","id":"69b9dc1c-9178-4090-82d2-4ecb650bf8a6","last_modified":1509744762617},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723337Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3UNTBOHUkbq+k999nJeSJdF","id":"12f76ac6-cb54-42d2-90e2-a06fbf6cc681","last_modified":1509744758183},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723335Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3TWA5Aylxw0x8bVvrmUSNJd","id":"6765cc1a-15e0-46e8-b74a-30a03f538885","last_modified":1509744757639},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723332Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A1V4dX0tTb1rdTZxdWcuZ7YR","id":"fddf483c-b881-4a58-a24c-03b0f46ca701","last_modified":1509744754400},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723329Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A0BOaf9UbJxzqBudSyes/cEM","id":"21c2287c-c873-4a06-bd80-8c2498deee0c","last_modified":1509744746034},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723327Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AzL4tLuklekJ8lSh6VnRMSrk","id":"fe19f480-7306-4eb4-a434-bb21e983102e","last_modified":1509744744506},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723324Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AyjNQ4dnGD3FD6WL5gYrYru7","id":"22ef2da0-8e63-40fe-8644-667178538911","last_modified":1509744743907},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723321Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AyYMguSo1my449OZq51C3s3Z","id":"bbb3fb02-ff86-44d0-859b-9b827c4943ad","last_modified":1509744743316},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723318Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"Ax6Jm7ajV49tqHgf9nYnzRCI","id":"f2b5d0ef-312b-4de2-9cd6-e0fb9bf262df","last_modified":1509744742729},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723315Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AxW0+uDsfyCSfhECdsGGpVD8","id":"0266840c-ce0c-47c1-8816-2c4f4b29b3f4","last_modified":1509744742199},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723168Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AwBGo0Zmp6KRryAguuMvXATI","id":"d5c21685-054a-4233-a633-0af3d769b0e7","last_modified":1509744741583},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARU=","id":"b91f4d33-972a-42ab-859f-0d3c8b68efe4","last_modified":1507714028770},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"RqFXxGPuA18=","id":"c75a0024-f08d-49e1-b8fc-1ca9bbb47965","last_modified":1507714027119},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhPSY=","id":"ddb917af-e251-48bc-91eb-59076ddf8494","last_modified":1507714025550},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhNLo=","id":"e606e8ce-32ef-4ffe-b9fd-7eced767b9b2","last_modified":1507714024574},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhOT4=","id":"259ff0a7-151c-4b7e-b449-98922b6bbfe3","last_modified":1507714023126},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"AeNmeF8oVpDp/4GPvA==","id":"82e8996b-8424-4e5d-849a-9cb6c134773b","last_modified":1507713902396},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJERTEQMA4GA1UECgwHU2llbWVuczERMA8GA1UEBRMIWlpaWlpaVjAxOjA4BgNVBAsMMUNvcHlyaWdodCAoQykgU2llbWVucyBBRyAyMDExIEFsbCBSaWdodHMgUmVzZXJ2ZWQxITAfBgNVBAMMGFNpZW1lbnMgSW50ZXJuZXQgQ0EgVjEuMA==","serialNumber":"WW8OCQ==","id":"a8ba8579-79d8-494e-b5bc-f9b8a6efae71","last_modified":1507713900874},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJERTEQMA4GA1UECgwHU2llbWVuczERMA8GA1UEBRMIWlpaWlpaVjAxOjA4BgNVBAsMMUNvcHlyaWdodCAoQykgU2llbWVucyBBRyAyMDExIEFsbCBSaWdodHMgUmVzZXJ2ZWQxITAfBgNVBAMMGFNpZW1lbnMgSW50ZXJuZXQgQ0EgVjEuMA==","serialNumber":"AaoZYg==","id":"316627fa-3b68-48e4-909f-9fc58fc69a62","last_modified":1507713899233},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydCwg==","id":"7696b73a-52f8-4902-b6b5-130d22222f15","last_modified":1507713897487},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BEeJFwO0nu759EPo9tKluw==","id":"113485f8-45db-488e-b45a-7917fcf4878c","last_modified":1507713895927},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402158","who":"mgoodwin@mozilla.com","why":".","name":"Certinomis Cross-Signed StartCom certs","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"Wu0lOm5kylP5uOu6md4xmWC3AtQ=","id":"9945629e-f285-47fd-9241-05cb75c041e6","last_modified":1506372739199},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402158","who":"mgoodwin@mozilla.com","why":".","name":"Certinomis Cross-Signed StartCom certs","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"Z7mwlz4NA2s+8dnwRzT/RvK9ZZQ=","id":"0f1e6e75-0f69-407f-bccd-5838401393eb","last_modified":1506372738063},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402128","who":"mgoodwin@mozilla.com","why":"These issue only client certificates and do not need to be trusted for SSL/TLS server authentication","name":"Add Cart\u00e3o de Cidad\u00e3o to OneCRL","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"a0zzyZD4OEdRpzTBCGWFnQ==","id":"b931ec9c-45a9-4719-b2fe-fd6c903b63f1","last_modified":1506372736800},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402128","who":"mgoodwin@mozilla.com","why":"These issue only client certificates and do not need to be trusted for SSL/TLS server authentication","name":"Add Cart\u00e3o de Cidad\u00e3o to OneCRL","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"ObszBuNYqt9If26rE5MLnA==","id":"1aadc1b7-2a94-4178-9ccb-64ba471135b7","last_modified":1506372735297},{"schema":1552493011443,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"CcaPWuZtcdneSnerYJH33A==","id":"2f081df6-2a06-4a11-ba8a-368275363e9c","last_modified":1506372734155},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DL0FAAzqeadFvWvsl9xaiA==","id":"07eff59c-72ff-4fa5-bdf6-756974fea58c","last_modified":1506372733055},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydWSw==","id":"f5108d78-08e8-4a73-b7e6-5722bc181931","last_modified":1506372732025},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1394595","who":"mgoodwin@mozilla.com","why":"Unknown","name":"Add Firmaprofesional subCA Santander Digital Signature to OneCRL","created":"2017-09-07T11:55:05Z"},"enabled":false,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"QwCyx4wTlCQ=","id":"56e5b51e-6b90-4b87-8ca0-4f58d49e648d","last_modified":1504798798154},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1393281","who":"mgoodwin@mozilla.com","why":"Unknown","name":"Add FNMT's AC Representaci\u00f3n certificate to OneCRL","created":"2017-09-07T11:55:05Z"},"enabled":false,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"YcLU1PaprndVkma5ja/WIQ==","id":"756c3e21-c95d-4e5d-b5cb-00da9d658a78","last_modified":1504798796757},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"UWMOvf4tj/x5cQN2PXVSww==","id":"0b0401dd-4f39-4740-b911-6ab11ab5edb3","last_modified":1504710470915},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"AINVG9I4T2jgQgW4N9SNhw==","id":"a1d4104f-7bf3-4c00-9174-29b580030fee","last_modified":1504710469413},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BUE=","id":"d081997f-6074-4f9e-b5b8-aa572a1d3177","last_modified":1504710467840},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1392378","who":"","why":"","name":"","created":"2017-08-21T20:42:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeLBg==","id":"e130c036-75e7-4e76-a93a-392fb9568b30","last_modified":1503344586238},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST EV SSL Sertifikas\u0131 Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"AUMyuCiycPJJ","id":"e8c04b9e-6bbd-4fbf-bcb0-a2177ac9c04a","last_modified":1503344585208},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST Nesne \u0130mzalama Sertifikas\u0131 Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"Aay2vr4aoUeZ","id":"af014072-16c1-4375-94ac-e8ee7611ccd3","last_modified":1503344584093},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST Basit Elektronik Sertifika Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"AZkNBFXrl1Zg","id":"5b62df54-5b45-424c-b126-a6442013861a","last_modified":1503344582959},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1391095","who":".","why":"https://groups.google.com/forum/#!msg/mozilla.dev.security.policy/Qo1ZNwlYKnY/UrAodnoQBwAJ","name":"Add AC FNMT Usuarios certificate to OneCRL","created":"2017-08-17T17:54:25Z"},"enabled":false,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"RV864VwhzbpUT4KqR1Hr2w==","id":"5e3a7625-ad9e-4713-89e7-3cddd3c0a781","last_modified":1503344581693},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"ATk=","id":"b2eaf8f3-f13b-4294-9a7c-5f70cda440b0","last_modified":1501513259932},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"ANU=","id":"d91f7502-e635-4fa6-b2da-9dcbac7a73b5","last_modified":1501513258828},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"QOu0a5Z9rCkw6Nk7Rg1/AQ==","id":"c302fc31-c64b-4105-bec4-2895e7201f97","last_modified":1501513257806},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"Xmo3AIW2VHeeJoR0o09RGQ==","id":"5be4587b-7e7d-4362-90ae-ec54e5c84a59","last_modified":1501513256610},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"SeEzbpTltqUtqW7UiuJ2","id":"8dd80d48-07b1-419d-9992-dac30fced89e","last_modified":1501513255352},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"RMgdRGEBv0KzFCjgGFp0Hg==","id":"5f913c3e-d525-4ecf-b374-45e1e40d75b1","last_modified":1499778717805},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"E/YGRk12iZqZuMfsIiVaeg==","id":"398c4ee1-de04-429c-8dbb-cdc0c232b145","last_modified":1499778716926},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"O2Qh+qhbBRuZA11yDhcLGQ==","id":"d87aa7c0-507c-4795-b4c5-812e387c3eab","last_modified":1499778716028},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"D/VlGqmz9Nai1ywCydT/RQ==","id":"6094fb26-7fbf-48b0-83b0-42750450cb4e","last_modified":1499778715137},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"B8f7CHJUqV3VareLPE+2kA==","id":"33c37dfe-6270-49e8-b437-e593e6905679","last_modified":1499778714260},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"HVRikKXRQ1ouhOpYcOna/A==","id":"18c1851b-db94-4913-8688-368d7ed7bc61","last_modified":1499778713388},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA3IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNA==","serialNumber":"RmI44ARDVCUOgXNK9ACAbg==","id":"f4213dc2-9eb3-44a8-8be4-accb6d408075","last_modified":1499778712492},{"schema":1552493012878,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"Aj/CJN2QWZAF25GXPXADOA==","id":"03a9b3e7-7787-41db-98db-e2fbd024ef45","last_modified":1499778711624},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQQAAATjkOB1sAAAAAg==","id":"1b74aa7b-2506-48bd-88bc-39af44ee70ce","last_modified":1499778710731},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"JGKKnm00uOQ=","id":"c6c10916-eb0c-4c4f-a812-4d6390e8a738","last_modified":1499778709784},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAlVTMQ0wCwYDVQQKEwRWSVNBMS8wLQYDVQQLEyZWaXNhIEludGVybmF0aW9uYWwgU2VydmljZSBBc3NvY2lhdGlvbjEcMBoGA1UEAxMTVmlzYSBlQ29tbWVyY2UgUm9vdA==","serialNumber":"B2VhZAPxCDH3s9Mkbu3HfQ==","id":"4961246c-b140-4db0-87d7-d240f049b67e","last_modified":1498049030788},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"ANUANvVYN7xqAISA9rvJPzQ=","id":"bdb19be5-1d67-49a9-bd7e-a7bbd8dcccad","last_modified":1498049029660},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQQAAATjtdPY5AAAAAg==","id":"fe6d33ba-fc97-485c-9b8a-639dd6d150d8","last_modified":1498049028433},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1374809","who":".","why":"Private key leaked","name":"Leaked private key for Cisco cert","created":"2017-06-21T12:45:09Z"},"enabled":false,"issuerName":"MF4xCzAJBgNVBAYTAlVTMTAwLgYDVQQKEydIeWRyYW50SUQgKEF2YWxhbmNoZSBDbG91ZCBDb3Jwb3JhdGlvbikxHTAbBgNVBAMTFEh5ZHJhbnRJRCBTU0wgSUNBIEcy","serialNumber":"ZhcM4uyLfYi04utzLnOP46Z89nI=","id":"bb8ba6ba-4e19-407d-ab9d-9f8aafd2c312","last_modified":1498049027284},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372336","who":".","why":"Banca d' Italia does not have a current audit for Baseline Requirements compliance","name":"Banca d'Italia Root's X-Certificate","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemaA==","id":"7df83512-01f2-4d2c-af53-fcf4d87defd9","last_modified":1497542609610},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"RsdOCxepZXHEs1ErwPc=","id":"b21c90ad-5618-40c1-ac75-eaf73b2c333b","last_modified":1497542608552},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByembQ==","id":"e7397769-a603-486d-9696-84693b277203","last_modified":1497542607254},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byemaw==","id":"148f7a38-535a-4097-a7a5-83abc4e35800","last_modified":1497542606104},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:06Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"MWzraR3LLhU9m/qKEhvVLQ==","id":"47786d55-ed71-461d-8ea0-3b074caac874","last_modified":1497362467654},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:05Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"eViJ2GX26lp5HbF+XNp1kQ==","id":"38355da2-f5ab-4882-a7e8-78ea5fc41e39","last_modified":1497362466761},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:04Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"U3KGm6UTqJ/nsMyteiUa2g==","id":"071f5229-616f-4ad1-a506-b48a9dbce21c","last_modified":1497362465694},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:03Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"OgxXyntHYBXnPAHDxY0OXg==","id":"95b7cd91-57b5-4e72-aa52-6a0546883af5","last_modified":1497362464680},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:02Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"GTPOETOFf5mIsbuzrojGfw==","id":"a7e4d7b5-50b7-412f-8592-ceb4f6db29a8","last_modified":1497362463643},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:01Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"NpsJHyt3o1U47AAgw3UNXA==","id":"f2e9d2ab-7220-460e-b4a4-02f3675e7a66","last_modified":1497362462415},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:00Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"RbG+tfPUe/vBRfTZF54i8g==","id":"9d320894-4ac4-49fb-bfcb-a71d97ebfe01","last_modified":1497362461438},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:59Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"dhjnNtYx6cojdAE55TgIBA==","id":"fd51db5c-9e30-4cdb-9736-1f10b80376a9","last_modified":1497362460372},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:58Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"Cf0103tCm9oulH1QK0weTA==","id":"a02fbc88-df3e-4d81-b9e3-7a7088e193b0","last_modified":1497362459446},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:57Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"GuJ0aGBYhChXAOljooJZ3A==","id":"375b3822-bf9f-4c3d-8633-02f7a03597ac","last_modified":1497362458420},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:56Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"OOkLFZaa4CXGyJlLTIEjUQ==","id":"815b19c3-6c68-49fd-b9c4-f488317c9e8e","last_modified":1497362457510},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"A/kVDQpE7c9h+WxlWQFzSQ==","id":"ae9bb73c-5360-4685-a5e9-8098b95617d5","last_modified":1497362456459},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:54Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"VP3bQF/UdNfxq/UOypU1zQ==","id":"9e057902-89e3-49eb-9e56-f878c1c05f4f","last_modified":1497362455630},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:53Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"G8sz+bm+vQjTpQNBh5CfMg==","id":"d7283b5c-18aa-4cda-9158-fae5ae41ad09","last_modified":1497362454734},{"schema":1552493014308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:52Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"PmDn14AwWY28IlJeBXkDvA==","id":"43838f76-1ecd-4a7e-9a81-f9f2449f31f1","last_modified":1497362453713},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:51Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"aBXsv0oU3xqh2xkUPOi8","id":"380057fa-8d61-4ee2-a6a1-f6bc5d210e40","last_modified":1497362452684},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:50Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIZ6Wq/4deFQzwC6NnFpUA==","id":"15c3777b-b91b-461c-99c5-761d6185b109","last_modified":1497362451663},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:49Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"APiyCXmwAUq+95DYa3DmGw==","id":"583ee36f-2136-418c-bab7-2d5ed62aad0a","last_modified":1497362450536},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:48Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9vdCBFViBDQSAy","serialNumber":"AL691kTvkemG9UQNa6McQg8=","id":"a2fad4bd-2ce5-4ecf-97e2-1612bde41ed2","last_modified":1497362449522},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:47Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"AI7cApIcPA3cfSpQMf40onQ=","id":"7b9f5e88-b3a1-4071-ad7f-fce8459aa3a5","last_modified":1497362448476},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:46Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"OUOBG6TE0Lr+uYYGxeVbHg==","id":"418575d9-15aa-4b24-9ba5-3764748e3245","last_modified":1497362447464},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:45Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9vdCBFViBDQSAy","serialNumber":"QFLH3Zrq+I5WQ6TlWzfUxA==","id":"65123c45-adf1-40a7-9531-a66d818ae6ab","last_modified":1497362446438},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:44Z"},"enabled":true,"issuerName":"MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"fqRDfSf8haCEh2nWE6O+bA==","id":"07e6dcee-ed47-4aa9-bc69-cd8c50be9eaf","last_modified":1497362445416},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:43Z"},"enabled":true,"issuerName":"MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"eohOGeS5ZHJeptyBvCu/mQ==","id":"11009f24-3e40-4372-82cb-c640be931a51","last_modified":1497362444493},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:42Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnY=","id":"d4cc9f44-f6a3-416d-92f5-d9d1242eff77","last_modified":1497362443469},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:41Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm0=","id":"d448448b-1f23-4815-a563-c4a7996615ce","last_modified":1497362442343},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:40Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnQ=","id":"04f35e34-8280-4b48-a5b3-bb61b27445be","last_modified":1497362441423},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:39Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnE=","id":"133ff174-70c2-4cdf-b8d4-4bcc3db4b004","last_modified":1497362440295},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:38Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"LYTXWk7gMu8=","id":"3b0df03c-394f-43bf-bafd-6da07eca3c10","last_modified":1497362439285},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:37Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"azAcTWL+ijs=","id":"0e15f9c5-75e7-4b8c-9f10-99f8998eda98","last_modified":1497362438146},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:36Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE6YA==","id":"73604eec-92dd-48a5-a040-b5644c4c9799","last_modified":1497362437119},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:35Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE6Xw==","id":"7e3d897e-9724-443f-842b-2124ee1cd062","last_modified":1497362436009},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:34Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE5Ig==","id":"cfe99f95-d3d1-4d4e-b312-6a7a0efedf09","last_modified":1497362434869},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:32Z"},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"f43O9TualR8=","id":"ab95e89b-21cc-49c0-b4ac-0d1a3773b334","last_modified":1497362433845},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:31Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABL07hW2M=","id":"a2b93b68-1670-4c9d-a94d-e792364d24d4","last_modified":1497362432728},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:30Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABL07hXdQ=","id":"9aba77c3-ae07-443c-a0ba-ca01aadcc3eb","last_modified":1497362431692},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:29Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hRxA=","id":"9065a612-801b-4b7b-9e2b-b87d584332a0","last_modified":1497362430669},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:28Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hSVI=","id":"b1bb540b-be1b-4011-81df-998edb912fe1","last_modified":1497362429542},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:27Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/UQ==","id":"891cdd11-90ff-435c-9688-1a9e7aeb3a70","last_modified":1497362428621},{"schema":1552493015730,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:26Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Tw==","id":"43770c43-8568-4d25-b5f2-52623d4fcf78","last_modified":1497362427700},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:25Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeBQg==","id":"9ea34ca2-9f9d-483e-8a49-c3a17d055d47","last_modified":1497362426780},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:25Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Tg==","id":"3d2ac953-a4f2-4f59-a7a6-7c9a8fadf2ca","last_modified":1497362425753},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:23Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/UA==","id":"78529990-77c3-404e-93bf-308ebf7033e9","last_modified":1497362424834},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:22Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Ug==","id":"91e8f996-738a-4ff5-bf6a-4823c963d8e5","last_modified":1497362423604},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:21Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJhw==","id":"7e2f71f1-6463-460c-b6ce-2a8b25624d3a","last_modified":1497362422585},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:20Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeekA==","id":"9a55265f-72e6-4e38-b23b-b3f097136daf","last_modified":1497362421456},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:19Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bycfmw==","id":"d29166c7-29e9-4b00-878f-99f6a415a4d2","last_modified":1497362420326},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycfpA==","id":"b02d1c65-499b-4cf9-a2e5-cd3d172c06f6","last_modified":1497362419199},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:17Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpYA==","id":"b544067a-575f-417a-ab9f-a9ef880c262e","last_modified":1497362418087},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:16Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydIoA==","id":"f91cf838-8125-41b5-9f6f-46891375de0d","last_modified":1497362416981},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:15Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"GA==","id":"a980e313-d1dc-41dd-9bb8-921862a834be","last_modified":1497362415923},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:14Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"Eg==","id":"8e1465de-a917-4608-b44b-ef02800eeb0a","last_modified":1497362414917},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:00Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"HQ==","id":"d61c0990-8c57-4141-9fe4-d5a0f46371ec","last_modified":1497362413918},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"Rea7UUYH3jl33BryPIo=","id":"3f5a142c-40a3-4c89-9df1-a056702b984e","last_modified":1494458678750},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"RvCM2iRdkCE82ZOO2dU=","id":"3e1798dd-0356-44c2-917f-76b2f32ee998","last_modified":1494458667510},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"RdHgEmEIjdyRFWDRRlk=","id":"f8ebfd47-13fb-46c7-9b4d-334526c6ded9","last_modified":1494458658573},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R/j2qA==","id":"2ba77577-428a-4f7d-9d54-b088ecb696b2","last_modified":1494458649435},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jvb3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QAEy3RIAAAAAAAAMweH5dw==","id":"81126721-940c-454b-bd0e-f538cd5ab646","last_modified":1494458639464},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jvb3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"DL8=","id":"ff5d47b7-cb50-46f9-9da8-e778892a2caf","last_modified":1494458631103},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"AMs=","id":"6ff3473b-bd64-4b79-98c4-4622661c8e80","last_modified":1494458620210},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"AZ0=","id":"6aa5cbdb-19fb-4f57-9a4e-ddfbf06f50ae","last_modified":1494458595987},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"cx0HrIEQg8JHWTP7DzOxSQ==","id":"bcd2cb94-3cd2-49df-a372-50a258804cc1","last_modified":1494458581014},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"A4g=","id":"124dd7d2-59e3-4eb1-b93a-5e9a33cd6e4f","last_modified":1494458571110},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"A4w=","id":"0b21265d-dcfb-49c0-b9e9-e900412c1fdf","last_modified":1494458562276},{"schema":1552493017141,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"APt5i5rs4dIIQPwZdk9/ISc=","id":"058e5554-d206-4b11-9791-dff120803f83","last_modified":1494458553816},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"OGPFrg==","id":"f27c1519-908d-4dca-a797-024c43844b52","last_modified":1494458545573},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemaQ==","id":"cbc37076-9136-40fa-a079-4d443b7071ca","last_modified":1494458533053},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byemag==","id":"b9762946-8b71-40cb-844b-cafa2c0aed12","last_modified":1494458523822},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDtA==","id":"4b8b97f0-8a72-4ff1-af47-2fcd773c900f","last_modified":1494458510233},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydvrw==","id":"c3724a4d-2ed5-46a0-87dd-d7d339549c8f","last_modified":1494458498850},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQKEwVUYWlDQTESMBAGA1UECxMJUG9saWN5IENBMSQwIgYDVQQDExtUYWlDQSBJbmZvcm1hdGlvbiBQb2xpY3kgQ0E=","serialNumber":"UbQGvw==","id":"20dc1a34-8afa-4d47-856f-810cc0a6f229","last_modified":1494458484988},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"LAVIFm0MWZYH+Sv8Vf+IqkM=","id":"d8f28ce2-8ee3-41a1-9bc0-ddad36f7c72e","last_modified":1494458469413},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"QM1zZ4GZ4gfwpQtUYye3Ne0=","id":"e35ececb-f12b-4fe4-bef8-ff7c3099fbe8","last_modified":1494458454435},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"YUlF+VXF2FWFqCo472HfZlw=","id":"0e806ef9-c9d4-455a-a462-cbb897cd8e20","last_modified":1494458439140},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"IHj3eiEK3K1Xrpu1uvtBuvE=","id":"023bf60f-9ed8-41ef-8ccb-1bf993f3f973","last_modified":1494458422758},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"RVWTeb5EKqE7cy7MUD2oJ3M=","id":"e5723e05-8b15-4cdb-b996-4d36b419a431","last_modified":1494458398872},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIG+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQDEylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMg==","serialNumber":"UdNjvA==","id":"917e8337-dd57-4b8a-8994-2921f2fb69ef","last_modified":1494458377056},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA5iEg==","id":"16319df7-453c-d980-4624-d73d9cf43143","last_modified":1485907697001},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:37Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydSYg==","id":"ec171905-2990-30e0-74bb-9fc327c1c4bd","last_modified":1485907696954},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"Iqpyf/YoGgvHc8HiDAxAI8o=","id":"6fa017d2-461c-8de0-f8a1-ab0531097d8e","last_modified":1485907696908},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"Hwexgn/ZCJicZPcsIyI8zxQ=","id":"4df86909-6b1c-f7cd-c71b-bb4b895d441f","last_modified":1485907696863},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"RnQ3dg5KdDZs0nyFZk4=","id":"0971a89d-b11f-97c9-2ac2-f706757b75fb","last_modified":1485907696819},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"RnQ3dYovwvB0D5q2YGY=","id":"d739cdcd-0078-92a9-2c46-6a5231f3d888","last_modified":1485907696773},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"ALxyZmb/WL/wAuUiPK5oK/g=","id":"d6bedca3-c2b7-0402-337e-7788b9c97b85","last_modified":1484704581273},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkGA1UEAxMiQ09NT0RPIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"AKrMYlJmUUin8FOM/0TJrmk=","id":"42e2ce60-f40f-97a6-dd47-3ea2e2dd72d8","last_modified":1484704580920},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"e7wSpVxmgAS5/ioLi2iBIA==","id":"59b02ba9-97ec-924b-d797-2c61c2be0d87","last_modified":1484704580894},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydrxg==","id":"224d1360-5aed-b81f-f24c-3d34e2ca3ec4","last_modified":1484704580868},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc85g==","id":"25a0eefb-aa44-23df-4dda-bb166836d4c1","last_modified":1484704580840},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"CdYL9vSQCEKzBwjO10ud2w==","id":"479ac2a4-7b6a-8db3-c5a2-be10eb5dec57","last_modified":1484704580815},{"schema":1552493018551,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"fbsHfUkagQtznc3rtY1uDg==","id":"b1b1a5db-3c68-21be-8264-7146b0ee9e6b","last_modified":1484704580787},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"AJiU+bpWh2Uc4xFRf8GM9yA=","id":"60daf8a1-a929-0177-e7ba-76fff95fd20b","last_modified":1484704580760},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"Hnms0W0OxHSYE2F0XE97sw==","id":"55b72394-f4c1-3001-cf84-10f2068f2768","last_modified":1484704580734},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye2Cg==","id":"e2277fc3-1aac-7c20-0cb7-f4fd6c79eedb","last_modified":1484704580708},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"CMNfzETd7XxesS9FOUj9Mg==","id":"49251465-af0d-3e93-cb1a-9d0b2ac356b2","last_modified":1484704580680},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"XJ8pGvGNM9RIcLUG9YQjLQ==","id":"c83b4498-ea23-7723-1c2c-b673115792d8","last_modified":1484704580653},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"e9JTGBe45yw=","id":"20d69a85-62b2-72c7-1107-110b43d2aeb2","last_modified":1484704580623},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpGcmF1bmhvZmVyMSEwHwYDVQQLExhGcmF1bmhvZmVyIENvcnBvcmF0ZSBQS0kxIDAeBgNVBAMTF0ZyYXVuaG9mZXIgUm9vdCBDQSAyMDA3","serialNumber":"YR0zGQAAAAAAAw==","id":"4204c7d6-1838-5925-2461-1bc0e03515d4","last_modified":1484704580597},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AQw=","id":"f8c41076-a3f0-439a-9d5e-41e27e019a77","last_modified":1484704580571},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx","serialNumber":"ESDDtMgFFiaUfKo7HD9qImM7","id":"ec0960f7-7ae1-23e7-5006-6652da817daa","last_modified":1484704580544},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"RFlmmjulj6Ve7PfBi44nnw==","id":"0e7b9a2c-3604-5b89-4dff-796122174bdc","last_modified":1484704580517},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx","serialNumber":"ESBrHE7sFC7CQ8EM681xA3CY","id":"0595dc75-9356-ba32-a15e-05e3072b7f54","last_modified":1484704580491},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjpW","id":"b7e26b4d-bbe1-1c4e-ef9b-12471bcb9bf8","last_modified":1484704580465},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"a9rf7/BmG9JkKvRuy7J5QA==","id":"fcfc3b3c-0a59-d143-f5fd-7600dd8efa87","last_modified":1484704580438},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ZECgRdZEsns=","id":"4652f392-127d-a5bf-4ed6-b07b9fa72247","last_modified":1484704580412},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"AJBQSPqrEvDE2Hz8xH39Low=","id":"c279dd67-2ce1-e090-1e04-0c11fe3ddf8e","last_modified":1484704580385},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"frj5jTuqBnQ4fljPvVU3KA==","id":"85acb18c-16b6-12c7-83ae-1e0d94251362","last_modified":1484704580358},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfFnw==","id":"d0da2ea3-1cad-5c9e-4c75-c83acfeabc8d","last_modified":1484704580332},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByembA==","id":"fcd51190-7eaf-291e-b6e5-45e447de7291","last_modified":1484704580305},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"RH7WhshwXRK6f0VfOfjXgQ==","id":"003234b2-f425-eae6-9596-040747dab2b9","last_modified":1484704580277},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"SurdtfsuPcXXDpY2LkBpYO6BT7o=","id":"034627e4-44c6-fbf2-275a-4ed3431a4094","last_modified":1483471394790},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Er0moq4zwH8ke2pYafIKdg==","id":"85c81ed8-787f-ffcf-2a63-1be622db8d04","last_modified":1483471394768},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydiAg==","id":"9194c97e-3baa-0446-9642-0d6211c3f019","last_modified":1483471394746},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"eLumDUO40KwnecZLJxFM2A==","id":"c2cc63c7-5274-9901-5f67-0a13355a8aa8","last_modified":1483471394725},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Bw==","id":"92e2494f-f3cd-7638-7fe1-a3cb8d8939fa","last_modified":1483471394702},{"schema":1552493019982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"GpO48aJ8GngtwECqZhm/xA==","id":"bdfdc34f-ba9a-7b25-6cb6-24c547eb8a10","last_modified":1483471394681},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSgwJgYDVQQDDB9EaWdpZGVudGl0eSBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"Cw==","id":"7574eb9e-6978-dcb7-5a6f-d4c3dd855254","last_modified":1483471394658},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"IA==","id":"d82f446f-181a-5ac3-0ced-854e3cde100c","last_modified":1483471394635},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"OfJBIhFwAdQ=","id":"b8fdddf1-27c1-5f6e-58a1-295e2c8c0ea5","last_modified":1483471394613},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"MABJTA==","id":"71e08617-c00a-8b62-53c2-2a61e21e6155","last_modified":1483471394591},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"HA==","id":"6a6d36e6-8939-0a83-3fd5-c38652b165ed","last_modified":1483471394569},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:55Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSMwIQYDVQQDDBpEaWdpZGVudGl0eSBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"DA==","id":"460643a1-23f3-1beb-0f14-ecb4b6e26cc9","last_modified":1483471394547},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CLc=","id":"49eb43cf-91d4-66ce-1a86-b8674ff83d4d","last_modified":1483471394524},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==","serialNumber":"QAAnEQ==","id":"bb5c827f-3458-93fe-f80f-2982f0d19d34","last_modified":1483471394501},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjqK","id":"d6f9a6d9-d936-dfaf-d396-8ae96769ef10","last_modified":1483471394478},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNeA==","id":"02ec8a09-2ae4-cd2a-4fa1-5037fa945391","last_modified":1483471394453},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"JLiDzgpL7oFNgJN+jIjt7w==","id":"5631f49c-a1fb-803e-ecf2-3ba82ca79f2e","last_modified":1483471394090},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"BwImeaRkSZQLYwFREwKo3R1Jn+8=","id":"c2de8edd-fd89-36dd-63d0-d3a1df92274a","last_modified":1483471394067},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"HxT1XSjIpzjMprp9Qu1gYQ==","id":"46d4712b-6db2-ce7e-0efd-675f3be896cf","last_modified":1483471394046},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5sA==","id":"8acc0cad-dee8-7e2e-1799-e1a7b8b989c3","last_modified":1483471394023},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"BA==","id":"b9ac21bb-8c1e-e562-5418-bbf6f6323c45","last_modified":1483471394000},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"KuzHPJLdK5hNgJRo3R47Ag==","id":"91b7f544-9de1-efea-08d4-4ebafc9a3608","last_modified":1483471393978},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"B+U=","id":"86fe91df-ebb8-f20d-2031-2bc815b14a25","last_modified":1483471393956},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byeaqw==","id":"b97a8dce-04d9-7dba-6463-ae95d61524f4","last_modified":1483471393933},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"LU4d0t7PAsZNgJGZcb+o/w==","id":"efdf0a12-4ba1-f84d-a88d-fc384251583c","last_modified":1483471393911},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABIg08FMU=","id":"6c0561bc-fea3-ba35-bbdb-2b2672b67d36","last_modified":1483471393889},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjqL","id":"4be7b89c-27a6-e95e-c6f9-bf652d4a0b97","last_modified":1483471393867},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"FQ==","id":"89946691-d008-fd14-bd7a-443206d647c6","last_modified":1483471393845},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydInw==","id":"e1a83fb0-93df-deb8-68cd-17f4997ea58b","last_modified":1483471393823},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"JD1wxDd8IgmiqX7MyPPg1g==","id":"f5ad7ea6-4ac9-b9cd-776f-d2afb53fb91b","last_modified":1483471393801},{"schema":1552493021474,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SqA==","id":"ad8a2f72-7124-3e33-3060-414ce2bd8be3","last_modified":1483471393779},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"J8mznxvTvOR5p4Br3a3sm5j5iM0=","id":"d3f6b499-297d-e9c8-081c-44e2331bcf29","last_modified":1483471393750},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"AIChpbGNqu4XKp9J70syKEs=","id":"f184ba74-06de-9247-104e-160b6d210962","last_modified":1483471393727},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Cj0=","id":"c5fdcbc2-71d8-0a58-3375-0c7d92526cf1","last_modified":1483471393705},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Aw==","id":"0e8a05ee-feae-fc46-15b9-eaa2d11f4a60","last_modified":1483471393683},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABRE7wRk4=","id":"ac8d3825-3fef-6d3e-2690-7360d1ef57a4","last_modified":1483471393659},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5sQ==","id":"4b03d4c1-705b-458e-5bdc-f729f67eeb91","last_modified":1483471393637},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"WJ2qHzWUqTk=","id":"f93061a9-8afa-1d74-e063-4134d318f00b","last_modified":1483471393615},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"VUtahOwvvmJFwlvmGDZP5w==","id":"9c88bc12-466d-fcdd-cc53-349d4e041332","last_modified":1483471393592},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"L1fHogsVxmfMBka5q4uzaQ==","id":"d3c14505-c104-150c-0a2d-e5f9e92b6152","last_modified":1483471393569},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:55Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"cJ+vg4742XhNgJW2ot9eIg==","id":"58bf9d8a-9a68-b41f-453c-8af8844bc07c","last_modified":1483471393547},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"LizeWXFWP5pZPI/dLc+PVQ==","id":"cb1a1172-56d6-4150-1f50-eb2131f442f5","last_modified":1483471393221},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Ew==","id":"a0ff8e3f-e68d-5ee2-21e3-26cd0f46673b","last_modified":1483471393199},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABElatX7I=","id":"00ac492e-04f7-ee6d-5fd2-bb12b97a4b7f","last_modified":1483471393177},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"ANX8SnNRxCmsE/GCl5hw+8A=","id":"a09db9b3-2faa-73ab-67ff-61dcbf700ec7","last_modified":1483471393155},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"VBSf+IncsTB3RZS4KFCJPQ==","id":"7e816865-7c1d-2519-f114-e69a280768f4","last_modified":1483471393133},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSgwJgYDVQQDDB9EaWdpZGVudGl0eSBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"DA==","id":"5b760d02-fdd7-d6be-cb6f-4d30bf97746e","last_modified":1483471393111},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5rw==","id":"7de029af-ddf3-02be-ca26-5bb95b080d14","last_modified":1483471393088},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"MABJSw==","id":"411b4e82-2ddd-20c2-20b3-8d77145f6901","last_modified":1483471393066},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermwtg==","id":"9d8a83d8-d651-42a0-ac1c-0ee414f3e31a","last_modified":1483471393043},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"Nbc68Q8EHza72P/hSWcddw==","id":"d0513de2-6da9-d68d-78cc-a2292a9d18fb","last_modified":1483471393021},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Ig==","id":"872ba8c8-a236-9ac0-85ea-08630f5b17e2","last_modified":1483471392998},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"APdCebq8ZyZr/T0luxlicNw=","id":"7a24e461-9fd0-b17f-01e0-f44866b800f1","last_modified":1483471392976},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermw0Q==","id":"fff46511-7357-4559-3d36-75fc74034299","last_modified":1483471392954},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"Ajp/","id":"272f2a95-6aec-f333-22ad-709d6118a87b","last_modified":1483471392932},{"schema":1552493022903,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Fw==","id":"4f0dfd30-9278-4f20-25c3-436798595b84","last_modified":1483471392911},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"K1ftto7Xcb0YKwQ6uMvOIA==","id":"29eab149-524e-b1da-e2b9-dc4a784ab64b","last_modified":1483471392889},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAFQ==","id":"91609507-ef23-7672-3a5d-06dfb9b0dac4","last_modified":1483471392867},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"U+1Y1QpJc0FOR5JdCJ01gQ==","id":"79f39790-1151-6bb2-0a50-fc596b82bedd","last_modified":1483471392845},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TAA2G+UIK6mqznQKBT77NA==","id":"d51879d6-0a85-8311-5b14-ad993cec17e6","last_modified":1483471392823},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Iw==","id":"532dd854-cdef-6452-2793-1e36d091d9ec","last_modified":1483471392801},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/O5w==","id":"756ab100-8a14-daf7-bf06-9fe423863208","last_modified":1483471392779},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"Ajp+","id":"41f2401b-5c31-724f-ad6c-28f3f6f47634","last_modified":1483471392757},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkpQMRMwEQYDVQQKEwpGdWppIFhlcm94MS0wKwYDVQQDEyRGdWppIFhlcm94IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IDI=","serialNumber":"AUa47POQ1dN5","id":"0956d064-8750-eee2-b0c7-7e1c2d1d6f25","last_modified":1483471392735},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Pgyeh2mqlVzqI9hFntRbUQ==","id":"134969c5-0bf4-4054-eaa1-b24feaa76aef","last_modified":1483471392712},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Gg==","id":"141d8e99-193b-d108-382b-7d97e6912d8c","last_modified":1483471392689},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDYXNBhF+dePFjojs7u2vj1","id":"f7f193ca-c34e-866a-8abf-d44188a78cb0","last_modified":1480349168043},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA6BjA==","id":"2a9d41c8-d3e7-a40a-a79a-899902aa73cb","last_modified":1480349168021},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"XhcFm2g619rt8Sro+a4rHA==","id":"a01f2d94-e1ee-2139-5652-c216331e357a","last_modified":1480349167999},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F6QlB/yX+A==","id":"a7fa8b99-3e2a-2c03-dffd-ab341eae59af","last_modified":1480349167976},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydxog==","id":"35f6f9f8-eb17-39d2-50a7-2b40f01e2584","last_modified":1480349167954},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CqnbFQ==","id":"3b60bc42-674b-7822-113f-c8dc6d1b015e","last_modified":1480349167931},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJzdC1IYXJkd2FyZQ==","serialNumber":"Xrr31RF0DoIzMKXS6XtD+g==","id":"c0d2651b-f567-0f6d-ce3c-16e7d19390d0","last_modified":1480349167904},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SnQ==","id":"7326aa15-9b3e-44ca-c1c5-0ed1ff29521f","last_modified":1480349167882},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzQ=","serialNumber":"H08=","id":"2ac02b19-f616-0dc3-6d01-28e1bea3dd93","last_modified":1480349167861},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:22:27Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"NMpMcEnex3eXx4ohk9glcQ==","id":"8e453b5c-3f81-2694-2f10-73ec8c406c49","last_modified":1480349167827},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAA=","id":"a3b400ad-0b4d-aa11-e8b5-82019fbc84d5","last_modified":1480349167797},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIGpMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykgMjAwNiB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UEAxMWdGhhd3RlIFByaW1hcnkgUm9vdCBDQQ==","serialNumber":"Ikdj3zYXXGsC/Afm9Tvx+g==","id":"e8b2d24e-5aaf-86dd-441e-b4781d5370db","last_modified":1480349167774},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgQ2xhc3MgMyBFViBTU0wgQ0EgLSBHMw==","serialNumber":"acI1CFIgmwSFBoU5+ahDgg==","id":"938358e4-4c70-beb4-0fbe-02009feee6b6","last_modified":1480349167744},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:37Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABA/A35EU=","id":"97fbf7c4-3ef2-f54f-0029-1ba6540c63ea","last_modified":1480349167722},{"schema":1552493024471,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgQ2xhc3MgMyBFViBTU0wgQ0EgLSBHMg==","serialNumber":"UVKsEezpGWOVQ4W9esstng==","id":"c4c22010-0cb9-e9af-005d-2483612d864e","last_modified":1480349167701},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg/C8eXg==","id":"4295bb93-6e34-a58a-4d1c-238615b57cb0","last_modified":1480349167343},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AImQERVYPoeb","id":"4ca8f1a1-0dc0-881f-b497-cc5574f2494d","last_modified":1480349167322},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"J2La+q+JOURNWkX60OP2lQ==","id":"8662e9a7-fe16-d1fc-0993-d16dd2f01012","last_modified":1480349167291},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDEgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAxIENB","serialNumber":"BAAAAAABHkSl5ao=","id":"7cfc5a53-f950-c15b-4dbb-8124fadcf871","last_modified":1480349167269},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"RUT1Gehd1KKYPfqOlgspoQ==","id":"8855fafd-e48b-680d-ff15-a022057d9b9e","last_modified":1480349167246},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:26Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABKUXDqxw=","id":"0a92faa8-b870-3a38-036e-9b95185fcb6a","last_modified":1480349167224},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"CqZgEvHAsnzkT//QV9KjXw==","id":"39008976-298e-f664-50c0-56f8ae6c4df5","last_modified":1480349167202},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR8wHQYDVQQDExZHZW9UcnVzdCBTSEEyNTYgU1NMIENB","serialNumber":"OUvvVscW0/NltofkmV9qmg==","id":"a5eb3877-5e7d-200a-cee3-f63b8004d58e","last_modified":1480349167179},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"ORFgmCj072NjcJnrxOMfQA==","id":"995df7f2-6bd4-12c6-b1aa-fcfe7618b193","last_modified":1480349167156},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltms=","id":"460ae779-c915-9daf-9a13-e0bf953322cb","last_modified":1480349167125},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155119","who":".","why":".","name":"T-Systems intermediate certificate","created":"2015-05-05T11:10:09Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARQ=","id":"2826cef9-e4b4-53f9-e3cf-c5870fc778dd","last_modified":1480349167102},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:49Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"DAk9hy8DhHSo+aQetvPB/fY=","id":"b42066e0-0c88-e02b-620f-c41c2118c4e7","last_modified":1480349167079},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1309305","who":".","why":".","name":"Hongkong Post e-Cert CA 1-10 certificates","created":"2016-11-03T12:48:38Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BHk=","id":"5048a7c5-79c8-68d7-06a3-19e8ba32e5fc","last_modified":1480349167057},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"OnvXX72mvUI2Id/NMzegmg==","id":"92d843e8-4e72-2832-b56f-6e488e677d0f","last_modified":1480349167035},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEiMCAGA1UEAxMZR2VvVHJ1c3QgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"ZgwfEqZnBsUNvNuZ77FbQA==","id":"73ae5fed-730d-94db-04ef-2aafd5ff75b8","last_modified":1480349167012},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/QbQ==","id":"6e4739fe-1aed-2320-4dc3-832043a31fc8","last_modified":1480349166989},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"L79XLVO2ZmtAu7FAG8Wmzw==","id":"7d2a48b3-0b2e-59ae-2002-8edb4da20bd2","last_modified":1480349166968},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"BUrYjru5px1ym4QUN33TOQ==","id":"e95bb238-6d35-2cce-9744-d6a672b0a874","last_modified":1480349166946},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESByNJZ5TPjg9iZyL6a/h5Zx","id":"51935a37-2964-18cf-b34c-a20c2c2250ea","last_modified":1480349166921},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1314673","who":".","why":".","name":"SecureSign Public CA11 intermediate CA cert","created":"2016-11-03T12:46:07Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RDQTEx","serialNumber":"Aw==","id":"ec4f91dd-7560-920a-f178-e8ae460dd595","last_modified":1480349166898},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABFUtaxac=","id":"8d87b3cd-b954-f4f1-bfb2-a0e60645301c","last_modified":1480349166876},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE3ew==","id":"83ac91ce-0f5e-ae4e-2010-b0da5616cd59","last_modified":1480349166855},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"LnfcUaXG/pxV2CpXM5+YSg==","id":"4c743a6f-af95-49a6-bd4a-d1ee8160c537","last_modified":1480349166833},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1309305","who":".","why":".","name":"Hongkong Post e-Cert CA 1-10 certificates","created":"2016-11-03T12:49:39Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BGU=","id":"4de7908c-45e7-3b7f-a91a-8cefb1ecf830","last_modified":1480349166811},{"schema":1552493026167,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:46Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJZbEU4I=","id":"19c9a896-fbf0-8ad0-92cd-4aca2577c006","last_modified":1480349166787},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABIg08D3U=","id":"4aec7420-aa59-53b8-1373-d3c0a7ebc837","last_modified":1480349166478},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQgAAAUFcf/EVAAAAAg==","id":"d60a94e9-3f7f-a20f-1dcc-c87ccc78fb99","last_modified":1480349166455},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"dItWlz2V62Philqj9m6Pbg==","id":"abb0df0d-6716-9a25-ae33-806e93276cd4","last_modified":1480349166433},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcL+EA==","id":"3cef2b9e-ddcd-cc40-8d59-49408409a3bb","last_modified":1480349166405},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1263733","who":".","why":".","name":"Disney CA intermediate CA certificate","created":"2016-04-12T12:50:50Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA6EVg==","id":"7b09e4fc-2261-e7c6-e926-5a7b5e74fc5e","last_modified":1480349166381},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"GdXz4L1b6FKNCMG9Jz2tjA==","id":"35f81fe8-9fa4-760b-9fd0-2de1b0191721","last_modified":1480349166358},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:23:14Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"COwoDFvz7GD8R2K7Lo0rYQ==","id":"cc56260c-5f3a-3f4b-c712-78a8e7facd27","last_modified":1480349166330},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEmMCQGA1UECxMdQ29weXJpZ2h0IChjKSAyMDA1IFdJU2VLZXkgU0ExFjAUBgNVBAsTDUludGVybmF0aW9uYWwxKTAnBgNVBAMTIFdJU2VLZXkgQ2VydGlmeUlEIEFkdmFuY2VkIEcxIENB","serialNumber":"WD1AyQAAAAAAJQ==","id":"8c984ecd-c61c-426a-97aa-3a808e4da482","last_modified":1480349166308},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnI=","id":"333f6eb2-cefe-1a3b-3726-a8320b047847","last_modified":1480349166286},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJQcQRNU=","id":"2258e9bc-1c39-9db3-4fdb-c7eb12d0609c","last_modified":1480349166264},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:15:54Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"Bg==","id":"b7fb6842-6407-8ae4-5e0f-e6daf112ed4f","last_modified":1480349166240},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"IIxFSyNM6mWtCgTG0IL3Og==","id":"6457eeb8-d83a-3818-c416-0dce6d71d471","last_modified":1480349166215},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABHkSl5AQ=","id":"de8e6484-fc97-6889-a1f9-dafd45786606","last_modified":1480349166191},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeQ9g==","id":"bb5a82a6-8da0-5390-a7d6-843bdb0c02c2","last_modified":1480349166170},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:17:01Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"EQ==","id":"dcce309f-aa60-6484-eaed-aa8310440a5c","last_modified":1480349166148},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4af5A==","id":"e60eeeb2-612e-ef08-d0b8-5e9f8e1a23a9","last_modified":1480349166126},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:51Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAAA+X/GIyk=","id":"528cd047-ef3b-fc23-e37f-5d67fd3117e4","last_modified":1480349166102},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"BYyEX2b5+K+myAIR7eXaRQ==","id":"9be08dd3-1922-fb30-77dc-5cfcf00164a0","last_modified":1480349166080},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"RurwlgVMxeP6Zepun0LGZA==","id":"22a74468-602c-f4ac-0003-be4ce0167258","last_modified":1480349166058},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBSb290IENB","serialNumber":"AJiWmg==","id":"1525b265-22d6-3253-079c-c4ffca58458f","last_modified":1480349166036},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCLRVuhcUZaluIgIVlRJx+O","id":"a6299e39-84a4-2dce-ffbb-751107660f4f","last_modified":1480349166012},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:20Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABCUVQ9No=","id":"a1d34c2f-4a03-0e35-ba5f-bc14138bcff5","last_modified":1480349165990},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:26Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABF2Tb8Bc=","id":"7e19f742-420e-dbe9-f691-2d19430d75b2","last_modified":1480349165968},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm4=","id":"20732fc6-dd20-fe76-b6b5-b78388b64bdd","last_modified":1480349165947},{"schema":1552493027652,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"fMTRbGCp280pnyE/u53zbA==","id":"44aa21e7-a92c-a0cc-6f6c-85b7ee52a87d","last_modified":1480349165925},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"d8AtKymQwkOPDBj+hjPzFg==","id":"014a5b67-d566-0767-c9d7-48e54115a69a","last_modified":1480349165591},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"Os2rnHWYhryvdOXfgan06A==","id":"dc94f688-044b-f8a0-79f9-5dc2d42e3edb","last_modified":1480349165569},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:19Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"e/fIfg2Dj2tkYIWVu2r82Cc=","id":"9e8ec7bc-0f79-42c2-c9bc-32bfbbd3b591","last_modified":1480349165547},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:16:27Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"EA==","id":"362a0532-ea75-9bc6-2e50-35d9566a6ad2","last_modified":1480349165523},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:06Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"UU3AP1SMxmyhBFq7MRFZmf0=","id":"4f2e59ff-cdf1-48ee-1122-961833187e49","last_modified":1480349165501},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESBqoILo90ntDW7OTK43MS2F","id":"0702b706-86e5-6a48-49fa-6c53b99009f3","last_modified":1480349165479},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"GtXUVojhwOTkaQ4bTKblEQ==","id":"9475e2f6-7247-cbe1-5055-8af86f39a149","last_modified":1480349165453},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"KjoVfZ3by6+pL8fssyfM6A==","id":"f4c8162a-d49b-1cbd-adb9-5e6223793aa4","last_modified":1480349165429},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydr0Q==","id":"a85aef34-3bfe-2135-845d-466adadc414b","last_modified":1480349165407},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Xbevr3ut3Z9m1GuXC9SonA==","id":"549710cf-bcaa-843c-df9d-5962bad88a9a","last_modified":1480349165384},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CeagHQ==","id":"d69db231-b7b5-4d79-147b-49198f93fc10","last_modified":1480349165355},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"EAdmaA==","id":"618009ee-0ef1-af4b-8841-349e6f82eacc","last_modified":1480349165329},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:54Z"},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB","serialNumber":"BAAAAAABHkSl7L4=","id":"636c65b9-2d52-8689-023f-7a23a0baec5b","last_modified":1480349165306},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABFqoAZoI=","id":"2b0d58aa-9c96-748f-4fc0-b1f413ca8e20","last_modified":1480349165285},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1250907","who":".","why":".","name":"IdenTrust cross certificate","created":"2016-02-24T20:04:54Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxIDAeBgNVBAsTF0lkZW5UcnVzdCBQdWJsaWMgU2VjdG9yMRwwGgYDVQQDExNJZGVuVHJ1c3QgQUNFUyBDQSAx","serialNumber":"fwAAAQAAAUrz/HmrAAAAAg==","id":"352c78aa-997c-bdbe-66ba-930d66fde011","last_modified":1480349165264},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CeFU2w==","id":"e8e298f0-efa2-0d08-458f-c085ee9df8f9","last_modified":1480349165242},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1149603","who":".","why":".","name":"MCSHOLDING intermediate certificate","created":"2015-03-31T14:53:16Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAjg==","id":"c9897d2c-c68e-3c02-2f39-678954b0cf3e","last_modified":1480349165209},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:35Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"bAOrKSMsmA0MLJyAJ5BRsUM=","id":"7d44cb3e-28a5-16dd-024c-796312f780bc","last_modified":1480349165175},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5BhE0zbgQ==","id":"29925947-91ab-16a8-a5af-65558cdb27c2","last_modified":1480349165145},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABL07hUBg=","id":"1240480e-2ef8-8ac3-4314-4e8e494741b9","last_modified":1480349165119},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCyHU+xOECnh9Rf2IvgR8zS","id":"3980401b-c0e2-0533-f0fb-0cc04685d248","last_modified":1480349165097},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CdWFNw==","id":"f06ff510-954e-b917-fda1-2c3153788d7d","last_modified":1480349165075},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TrKEMhb2PKktH8lHg0AV5A==","id":"8b7985ab-ab8b-fcd2-cf88-cf8dad0f7a97","last_modified":1480349165048},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:56Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJQdAjik=","id":"a75f5980-9149-fff9-70d5-b24121c3eaff","last_modified":1480349165026},{"schema":1552493029193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9lw==","id":"59b587cb-401b-a5d0-8128-86c3691c4be1","last_modified":1480349165002},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDMgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAzIENB","serialNumber":"BAAAAAABHkSl6mw=","id":"3cc60c06-a870-951e-1d12-4b29ee13989e","last_modified":1480349164725},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"SdegFrLaFTCsoMAW5ED+zA==","id":"9fbfe267-c715-8f7b-d9ad-166aad9f91af","last_modified":1480349164704},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABMxvC9bk=","id":"923a5e98-11f7-cdae-b073-45b525fb2294","last_modified":1480349164681},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydp0g==","id":"10e51569-072a-611a-c397-3050fdf22649","last_modified":1480349164658},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCrvQ==","id":"6d791114-68b4-8c3c-ee3c-29ed83eced2e","last_modified":1480349164636},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAI=","id":"bff9c953-6690-f618-cfea-7b936f3691a6","last_modified":1480349164614},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Aw1SPC56593ZCZ9vCNHKwQ==","id":"c395381f-fe34-7b6c-f56a-f20b20bf0d0d","last_modified":1480349164590},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:22Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABAJmPjfQ=","id":"24b096b4-987f-a21a-04d3-aedc9eaafc1e","last_modified":1480349164559},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABK84yjs8=","id":"8078d5ff-c93b-15d1-ebcf-607bdbfc159f","last_modified":1480349164533},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"FJl6tXgNpSk=","id":"7ab0a200-7ecf-576f-bff9-652fb14c3af6","last_modified":1480349164510},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"M0VSOewW3WI=","id":"f3688c95-3934-e80a-e32f-0d5dcb2f0c4c","last_modified":1480349164486},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"VN2yeFexyXjPf34fHGmbhg==","id":"bbcfc451-2fcc-b380-e579-bb6d11fc7d34","last_modified":1480349164463},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAeg==","id":"a46be506-1dbc-41a9-2775-95d67708fb5f","last_modified":1480349164433},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1300977","who":".","why":".","name":"revoked.badssl.com certificate","created":"2016-09-09T16:26:08Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQQ==","serialNumber":"Aa8e+91erglSMgsk/mtVaA==","id":"4b778ec2-ef45-c5b2-dc44-b00c87b11741","last_modified":1480349164410},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"TurPPI6eivtNeGYdM0ZWXQ==","id":"8192a2fa-165d-3759-fd20-4b7d8e2a0e84","last_modified":1480349164388},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAMTFHRoYXd0ZSBTSEEyNTYgU1NMIENB","serialNumber":"UKKK5ol/rKBZchAAOnZjaA==","id":"ca0c5f15-2808-8c94-3f77-6a277d6738b2","last_modified":1480349164365},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"UMUwXwT1Z4juyQ/CNTf4mw==","id":"c623e511-79c8-cbe6-6a6e-0d9896f07e71","last_modified":1480349164342},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dD","serialNumber":"Ew1ee9Jq7Q/Dig3ACF4V6Q==","id":"c011d2b4-73bc-27e5-3d3a-ab00be2a4d05","last_modified":1480349164320},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"XLhHIg7vP+tWfRqvuKeAxw==","id":"520c26f8-9a60-5949-0372-c9d93f9e95dd","last_modified":1480349164297},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"E5I2y6sIonl4a+TmlXc7fw==","id":"ee842f50-9d56-8fdf-fa55-8b55b8519b81","last_modified":1480349164275},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"Jq6jgeApiT9O4W2Tx/NTRQ==","id":"3b658f17-11f9-7550-d991-3e9a1397402d","last_modified":1480349164253},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDIgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAyIENB","serialNumber":"BAAAAAABHkSl6Co=","id":"6eb0fa3b-c226-f411-0fab-df88962a5769","last_modified":1480349164232},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESD9YhzIEOwiOT7Nwip+E1KI","id":"d6172148-c2ee-a904-db40-079b10436cca","last_modified":1480349164209},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:17:24Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"Eg==","id":"34561e12-916b-083e-6fa6-181b5b89ec80","last_modified":1480349164187},{"schema":1552493030646,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"NvEJoRYL2yvAZrAjbDIipQ==","id":"b1119d43-b3b8-1f41-6fbb-9cf2f67a521d","last_modified":1480349164164},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCC9oPNcRdPOox+SjWm9dTX","id":"8858e9fc-cc55-54ea-fe45-c4e533c2e410","last_modified":1480349163834},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1145157","who":".","why":".","name":"live.fi certificate","created":"2015-03-31T11:14:46Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB","serialNumber":"D9UltDPl4XVfSSqQOvdiwQ==","id":"0a9323dd-982f-c62d-a9b4-b9d04617fc62","last_modified":1480349163810},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:35Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"OYBKgxEHpW/8XGAGAlvJyMA=","id":"d6dfdc76-52ae-2843-3484-7fbff46f0100","last_modified":1480349163788},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"EM8bDLBnnoYe4LnWpLIhS4esr3I=","id":"be09b295-68d1-9c01-97ee-10df36acd3ea","last_modified":1480349163764},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:41Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJ/ufRdg=","id":"5d64f82e-9ad8-fde1-a8c9-2d94552a8ad4","last_modified":1480349163739},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:51Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHJRKMpA=","id":"f5b2da3a-5176-b4e4-240a-181f39f6756b","last_modified":1480349163715},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:18Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABBHYoIFs=","id":"f59ed73e-f3c5-eef3-4481-3ca8af0b0688","last_modified":1480349163691},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:37:41Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABHhw1vwc=","id":"1b1856c1-f4f5-82ca-ba57-d94739e74576","last_modified":1480349163668},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"TqfXw+FkhxfVgE9GVMgjWQ==","id":"60f6a3be-ad83-a868-d645-7aad77914bc8","last_modified":1480349163645},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:21:56Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"LdbnCbsA9sOgI4mkUpWXPw==","id":"d839b1ed-7d39-5e57-687c-2f4d6f0514e5","last_modified":1480349163622},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"ANygrItIJ2rcKlyS3Lue07U=","id":"d55572d9-be60-5967-948a-7dae793ab30f","last_modified":1480349163595},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydeGg==","id":"b7d8b0e0-9747-6a09-ab6b-051c57579fe9","last_modified":1480349163572},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCVop+Q4/OBgtf4WJkr01Gh","id":"7602529c-c2ea-d18b-9b2a-fdb70ca936f9","last_modified":1480349163548},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:31Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABGMG0Gmw=","id":"317aeda4-6de7-7b11-76cb-3b0afa9aaf86","last_modified":1480349163514},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:04Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"O2S99lVUxErLSk56GvWRv+E=","id":"27847bcc-dbaf-196f-ed5e-c1c022798717","last_modified":1480349163492},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:16:35Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"By7fBTreouRwX/qrpgSUsg==","id":"322de470-76d3-a45d-740f-342a6a8eb863","last_modified":1480349163470},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"ezdAeCxKH7BFs7vn3byYaw==","id":"fc5bde6b-45b9-c141-7171-0a6f37e7938a","last_modified":1480349163448},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"VLm3Xe60+1YgPpXCGtXLng==","id":"055d66b6-8fbd-93df-f2c4-dcdb41943212","last_modified":1480349163426},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUaGF3dGUsIEluYy4xGzAZBgNVBAMTElRoYXd0ZSBTR0MgQ0EgLSBHMg==","serialNumber":"cDggUYfwJ3A1YcdoeT6s4A==","id":"093f20b4-93b8-a171-cbe7-3e24a543c7e9","last_modified":1480349163403},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"a9/VeyVWrzFD7rM2PEHwQA==","id":"c02a9772-b351-59dc-8633-1293ac9addee","last_modified":1480349163377},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCis569omrbb20yySF39+aE","id":"aaa19866-32ce-e842-6431-6d357fafe8d8","last_modified":1480349163350},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg6C237Q==","id":"57ddfa31-3f08-298a-d7bd-712e3aaea567","last_modified":1480349163327},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"HZyLf+K70FKc+jomm8DiDw==","id":"452f4798-87d4-8df1-b275-177456d2f1c8","last_modified":1480349163302},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CskruA==","id":"e92cad12-4098-0817-e317-3674d4242ba9","last_modified":1480349163280},{"schema":1552493032094,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"a12RvBNhznU=","id":"33154d98-0f20-7e7d-d2d0-3244a7d1f971","last_modified":1480349163257},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CjM=","id":"283b292b-1212-a713-c8be-c976c0222410","last_modified":1480349162955},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"NTgf4iwIfeyJPIomw2dwSXEwtxQ=","id":"542dbfc0-0faa-2398-9670-cd249525fd2c","last_modified":1480349162930},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cd/dug==","id":"3cf54b7b-336d-7c80-4596-d5a7762329d9","last_modified":1480349162902},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"M64Z5ufZzDRVTHkJR1uXzw==","id":"5d6d86a0-7e3e-b832-83e5-afc1eb2e294f","last_modified":1480349162880},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABIBnBjWg=","id":"0713fba9-386c-888f-cbe5-5188ff2696a4","last_modified":1480349162857},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"fWK0j/Vi8vNWg3VAGjc02w==","id":"a4428979-4be6-3ba2-f435-aa8e4574ffe0","last_modified":1480349162835},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xGzAZBgNVBAMTEnRoYXd0ZSBTU0wgQ0EgLSBHMg==","serialNumber":"JpUvYJyWjdGmeoH7YcYunw==","id":"929de7d6-0669-5601-0b8f-9a192bf1cb17","last_modified":1480349162803},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"45KI4WIxyXfNrdtdj7C6","id":"7cb25ddb-9f7e-7297-e8b4-c50d019f0cf7","last_modified":1480349162781},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:15:22Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"BQ==","id":"7c28e9e7-b9ce-f4ed-8d5a-e7b9e534fba5","last_modified":1480349162758},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:19Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"F7PAjw2k0dTX5escPnyVOBo=","id":"3c7e3e8e-5c25-8fbf-0006-2c92256e0a4b","last_modified":1480349162734},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"Sx51x7V8pYe8rp7PMP/3qg==","id":"4006917e-3260-59cd-eb3f-f4d1167cf888","last_modified":1480349162710},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"DHmmaw==","id":"0abfb8ad-d1b7-5f0e-cbea-630f2424171d","last_modified":1480349162686},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcHC/g==","id":"cba8acd8-a291-1ad6-9581-ed647dd5d56d","last_modified":1480349162661},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:53:13Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATE0vw==","id":"fc71cbb8-4e2a-2835-d5be-4c48cd3650bb","last_modified":1480349162632},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABLF5/HXY=","id":"ca59600c-e90a-e85a-43b8-22bc76bb0e1f","last_modified":1480349162610},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"BXA=","id":"a44b5bf8-8158-1924-7626-e1ba2d2031f7","last_modified":1480349162580},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:24:01Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"VOcIuNbTqkpOMUyI108FOg==","id":"43e72628-c1a5-2091-2dcd-41bbde768c73","last_modified":1480349162557},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:53:40Z"},"enabled":true,"issuerName":"MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ==","serialNumber":"ATFpsA==","id":"325bb598-839b-f7aa-8a22-08ab8c09e803","last_modified":1480349162533},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:50Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"UV9aaDeNRNtQuXjRYk4Skhg=","id":"c11dd0af-83d5-61ec-63af-5b816a3ae557","last_modified":1480349162506},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"bzTw0uq05TUYEGS98bh0Ww==","id":"6b743fc3-1ce6-8dfe-52f1-9f3e6a31f15a","last_modified":1480349162483},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:21:30Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"Gd/pPu+qLnXUdvP9sW73CQ==","id":"2da11236-c2d8-7804-7de3-ffd711406b04","last_modified":1480349162460},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:09Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJ/v3ZwA=","id":"9f6615be-a0b9-519a-1e26-2bd7aaf5953b","last_modified":1480349162438},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:05Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABGMGjftY=","id":"5f1ab732-8d48-0102-fb50-46ce74fc1a90","last_modified":1480349162415},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"Rvm2CEw2IC2Mu/ax0A46QQ==","id":"82f97501-85ba-bb19-f68f-ca7ce68ca7b3","last_modified":1480349162392},{"schema":1552493033534,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABJpQ0AbA=","id":"520cee2c-e36a-936e-d551-a51ee9c659c8","last_modified":1480349162369},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfHkw==","id":"74d82589-0fde-91da-20cc-22fbd84cd0aa","last_modified":1480349161997},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESC8DawWRiAyEMd38UXbfgPR","id":"6147b64f-da46-ba30-2b9e-30b515e8f6b9","last_modified":1480349161969},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABK84ykc0=","id":"0a42070f-3149-2b91-1bbe-c54de4ed1be8","last_modified":1480349161946},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnM=","id":"dc28966b-d7db-b55f-1606-c5bff610bf99","last_modified":1480349161925},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"FJl6tXgNpSg=","id":"bab58b65-8ef7-f3c2-fc13-88f72a0840f7","last_modified":1480349161902},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDItX4ruWiLnrlz0rk4/bmz","id":"c12d5f3c-b722-948f-b367-857845ed5e8e","last_modified":1480349161872},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"bx/XHJqcwxDOptxJ2lh5vw==","id":"a0da0bd1-8bec-4c82-fb9b-636ddcde057d","last_modified":1480349161850},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:39Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"Mq0P6o03FDk0B2bnJ+mYPGo=","id":"54f096a5-3608-9b68-ddca-a200e799ba06","last_modified":1480349161828},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:00Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJ/ufQg8=","id":"61db13cb-74d9-e675-a1e8-db5f78eb3f4e","last_modified":1480349161807},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABM6d3Z0s=","id":"b9c439ef-fcf3-2263-c14e-80727cbef898","last_modified":1480349161785},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xGzAZBgNVBAMTEnRoYXd0ZSBTU0wgQ0EgLSBHMg==","serialNumber":"FNISyWWTGi5Yco6fGh58/A==","id":"bab0ff94-c98e-7843-97b3-a4d1e044715b","last_modified":1480349161763},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"VfTSum25nb65YPlpuhJAvg==","id":"91149dc9-6cc4-a670-1799-7bd05c159858","last_modified":1480349161740},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEwMC4GA1UEAxMnU3ltYW50ZWMgQ2xhc3MgMyBFQ0MgMjU2IGJpdCBFViBDQSAtIEcy","serialNumber":"OhrtngFwotLcm4i+z00SjA==","id":"337e2f4b-02c4-c70d-55be-09c8ea41731c","last_modified":1480349161718},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1181126","who":".","why":".","name":"RCS Certification Authority","created":"2015-07-13T09:05:40Z"},"enabled":true,"issuerName":"MDcxJDAiBgNVBAMTG1JDUyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEPMA0GA1UEChMGSFQgc3Js","serialNumber":"AN9bfYOvlR1t","id":"18c0d37b-739d-04c6-04f2-a615be5b9948","last_modified":1480349161696},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5BhENPfVw==","id":"72a65abf-9828-365f-4d4a-78457d7bdec4","last_modified":1480349161666},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESISuBo/wdW2tBztKmHdFCFz","id":"2ad44cbf-32ca-5245-c881-6d6f290ac2c1","last_modified":1480349161641},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1205651","who":".","why":".","name":"Misused certificate","created":"2015-09-21T13:21:25Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHjAcBgNVBAMTFXRoYXd0ZSBFViBTU0wgQ0EgLSBHMw==","serialNumber":"CrTHPEE6AZSfI3jysin2bA==","id":"13987e52-821e-1fe3-3743-393136b17167","last_modified":1480349161619},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"WX89jn8yGZVvoKTD9jDfRQ==","id":"a15c9fa5-cd6e-362d-1341-1e95c11c38fb","last_modified":1480349161596},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:22:54Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"JV/LVzSKI/wsDgg3UuZHlA==","id":"ba7935ef-b624-3eef-5ae8-a78044ec3af0","last_modified":1480349161575},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:46Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"sPNcCSE9Nkg3jy5IN1xe2Q==","id":"edc761c4-8b47-5314-0cd1-c894612ebfc3","last_modified":1480349161553},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"buROL/l2GuXISv+/JVLkdA==","id":"963548ca-bde2-1843-f140-1c26e8e40def","last_modified":1480349161531},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9oA==","id":"e85980d5-12f0-f624-7904-2d6cedeacd55","last_modified":1480349161510},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"IyIVazG4RE9AERkb+ekH8w==","id":"be3014a7-3d3b-08c7-02d9-5a74f601a1b1","last_modified":1480349161489},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"HNo1DR4XCe4mS1iUMsY6Wg==","id":"fd51f7d8-2006-663f-4779-3cf559ee5e74","last_modified":1480349161466},{"schema":1552493034992,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Ai7cBJYqBE0I9NdyoZfRrw==","id":"f7582bc8-dbdb-37dd-b24c-418242bbc4e0","last_modified":1480349161443},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"UUFV3S2cUidOOv7ESN65Ng==","id":"24ccf065-b88b-0fc9-1d1f-6c7722ca4faa","last_modified":1480349161103},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"EDQMI0tR4kSntv1O37N10g==","id":"e7509e16-1cd3-599e-2630-495ab52d3b71","last_modified":1480349161077},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:48:11Z"},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB","serialNumber":"BAAAAAABI54PryQ=","id":"e3bd531e-1ee4-7407-27ce-6fdc9cecbbdc","last_modified":1480349161051},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc68g==","id":"308f27b5-fc0e-da9a-2b7f-e65a1cb5cd47","last_modified":1480349161021},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEkMCIGA1UEAxMbU3ltYW50ZWMgQ2xhc3MgMyBEU0EgU1NMIENB","serialNumber":"AuhvPsYZfVP6UDsuyjeZ4Q==","id":"a0482eed-1e3f-7b9f-a433-94e4a4da49a1","last_modified":1480349160991},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:59Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABMrS7t2g=","id":"41a888b9-2e84-9782-69dc-d9153a3bd3aa","last_modified":1480349160963},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1197885","who":".","why":".","name":"SECOM intermediate certificate","created":"2016-07-21T16:52:32Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermwxw==","id":"1220feb9-9e66-0b24-3409-c5d1a1f8d24f","last_modified":1480349160941},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:36:53Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABCfhiO+s=","id":"e17ded97-6669-eecc-54fa-81f9a81ed281","last_modified":1480349160914},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1288354","who":".","why":".","name":"Symantec AATL ECC Intermediate CA cert","created":"2016-07-21T16:58:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA3IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNA==","serialNumber":"cXXMzbWDHMIdCotb3h64yw==","id":"a9970f7e-bac4-3b91-eae3-b0335ce0d1c2","last_modified":1480349160892},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"OqQ2rV0ISTc308Z/oQgzFw==","id":"781f8787-6508-d6aa-c508-13ac2bb0d930","last_modified":1480349160870},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cyr1PA==","id":"ec93f86d-fea2-7eea-42d4-7cf7a397e097","last_modified":1480349160848},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg+EziQQ==","id":"64229466-b4da-c63f-e088-ab1b5ba37930","last_modified":1480349160826},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:09Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABEAuMoRs=","id":"fe2dd507-9fc4-a6db-7ee0-255452bea28a","last_modified":1480349160804},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:24Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHlSo=","id":"04460239-09d9-2a76-191e-f344a8e5d0bd","last_modified":1480349160782},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:08Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABKB/OGqI=","id":"6b5475ec-8181-e7b8-4245-c7e2ffed213c","last_modified":1480349160759},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDu2nhlLPzfx+LYgjlYFP/k","id":"dc98c4eb-836f-6ca0-6673-6678fc45516a","last_modified":1480349160736},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:14:46Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"BA==","id":"765f426d-748a-5f3d-e409-35eac9be8240","last_modified":1480349160714},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"Aw==","id":"644e3fde-7ab5-556a-85ef-c5fac8b8c7de","last_modified":1480349160684},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGRuw=","id":"0a9335d8-3fa3-5d0b-7b27-72ddd14b5f74","last_modified":1480349160660},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd5cg==","id":"f046b001-5aa9-09b4-995d-23ad9f15db30","last_modified":1480349160638},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESJJweWBPhoXAaB9c8SHwI4O","id":"1bdc6228-2f9d-ad26-30b2-408959ede857","last_modified":1480349160614},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"LTRcDHabRHU=","id":"86e95439-a9f5-e04e-5241-268cf0186425","last_modified":1480349160593},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"YNOos6YJoPC77qwSGCpb7w==","id":"3c4f4898-da76-0a38-a765-18d9436285f2","last_modified":1480349160571},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHki0=","id":"e057bdab-4ad6-7e50-83ce-1099b84cce04","last_modified":1480349160547},{"schema":1552493036467,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"A9GPKQ8jv9oIxfwiOy7qxQ==","id":"4bb8966b-1db9-844d-4904-d823539cdf7e","last_modified":1480349160524},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cbssdw==","id":"661e65a5-ee0b-7a82-12c3-731cb560e112","last_modified":1480349160216},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcHC1w==","id":"26890617-93ad-e85f-550a-afb414cd110c","last_modified":1480349160190},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"DjIvBkX+ECVbB/C3i6w2Gg==","id":"657b91b1-9447-8c4a-db57-e0f0e2b10439","last_modified":1480349160165},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1150585","who":".","why":".","name":"XS4ALL certificate","created":"2015-04-07T11:04:11Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB","serialNumber":"UoRGnb96CUDTxIqVry6LBg==","id":"9084bc79-01cf-2ddc-b077-cd6c6251dd2b","last_modified":1480349160143},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"PAdKZPiaac2CvPxbOrsHOw==","id":"b79e2eb5-754d-4c21-1d8a-8c363f70dadc","last_modified":1480349160119},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxOzA5BgNVBAMTMkFyaXN0b3RsZSBVbml2ZXJzaXR5IG9mIFRoZXNzYWxvbmlraSBDZW50cmFsIENBIFI0","serialNumber":"EqthLKdUgwI=","id":"5b9744a8-bd65-b926-2920-8d8e5e1acd7d","last_modified":1480349160086},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEiMCAGA1UEAxMZR2VvVHJ1c3QgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"OE4/d+p3YRzzcSl+kmZ8Mw==","id":"fd2fe6f3-d095-5c3d-3c6b-afe00cb665c0","last_modified":1480349160058},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCrvA==","id":"32f968f5-4426-66ad-d1ab-9dda7b6f0c85","last_modified":1480349160028},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"AygWP2Fgd2T+iLbmAlKT6g==","id":"e23bcca2-1fb1-abd2-5ed7-892c5f08c4ff","last_modified":1480349159993},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CqL7CA==","id":"1a0c71ac-7f34-eeb0-2f71-1c14ee8e6552","last_modified":1480349159963},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"E77H6yvyFQjO0PcN3x0H+Q==","id":"be9e31eb-6a06-7699-708a-732a081a10c7","last_modified":1480349159939},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:04Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"YRJNfMoc12IpmW+Enpv3Pdo=","id":"3bb8f2d9-511b-121d-da29-23041d3c15c1","last_modified":1480349159914},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:54:05Z"},"enabled":true,"issuerName":"MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ==","serialNumber":"ATFEdg==","id":"4a17f132-602c-2d30-a781-145087794075","last_modified":1480349159890},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUaGF3dGUsIEluYy4xGzAZBgNVBAMTElRoYXd0ZSBTR0MgQ0EgLSBHMg==","serialNumber":"e0bEFhI16xx9U1yvlI56rA==","id":"07b97387-d755-0bbb-6e4c-616a7cb69cb4","last_modified":1480349159869},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnA=","id":"b3fb394d-f951-b49e-d856-f93028850feb","last_modified":1480349159846},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAU=","id":"2448ada0-833d-0d4d-3bcd-2c73cff02fb4","last_modified":1480349159825},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:03Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABCFiEp9s=","id":"5cef5dc2-95f2-0ac8-3273-153a09d3d227","last_modified":1480349159804},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CSY=","id":"b4c9041b-f5a5-dec1-b221-7286a32a6309","last_modified":1480349159782},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:06Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHJRKNmk=","id":"824e9b09-808e-e8cb-f2dd-ba669df011bc","last_modified":1480349159760},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"DYifRdP6aQQ8MLbXZY2f5g==","id":"59a292db-d567-6485-167f-1cb5af33f437","last_modified":1480349159739},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABL07hTcY=","id":"0a5a0233-bb8a-e4cc-5bb6-03cee44a07c2","last_modified":1480349159716},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"L7tgs/W85vnhV7I7qJ6N/g==","id":"e38e4e46-413a-eac8-9e85-1b9ee06f535d","last_modified":1480349159694},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:36Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABLM/7qjk=","id":"62dfeb32-e132-09a3-e4ba-e48c21d027de","last_modified":1480349159673},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:41Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHjz8=","id":"880134d0-617c-ec1b-3568-4c74af31bcc1","last_modified":1480349159649},{"schema":1552493037901,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9qg==","id":"9debdd66-d615-073f-26f7-011a8c54b484","last_modified":1480349159625},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAM=","id":"e4d16e1f-ac86-e9c0-2122-8a7d7d2dcdc0","last_modified":1480349159267},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESAyW/JX3+hZIp44EAMlXU2b","id":"6b135741-bfc6-1b3f-eb4b-4569aae2ab34","last_modified":1480349159244},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAQ=","id":"263f03a7-53f0-2140-89a5-46e7740d755a","last_modified":1480349159206},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESByYNtAIfizf2L3NMzCH8zZ","id":"853889e5-ad93-77ea-f9c0-a0907c9a3576","last_modified":1480349159183},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"BYOGvG32ukb1Yxj2oKoFyw==","id":"b049208e-5f4c-60a6-ac91-45f093defc33","last_modified":1480349159159},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"P6G7IYSL2RZxtzTh8I6qPA==","id":"222a4201-120e-64f4-5f6f-b2314470365c","last_modified":1480349159136},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls","serialNumber":"D/wZ7+m1Mv8SONSEFcs73w==","id":"d7fdf5b8-f8a5-b105-297d-d0e3617e59fc","last_modified":1480349159113},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"eR1nUEz8k+nDSBD+bb5uIQ==","id":"f6fb7b44-64cd-37b9-b9f6-fbe1210cb160","last_modified":1480349159091},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"QZBvapTZFvmYktEPsBYLQQ==","id":"b6f5b3ee-6cac-57a7-b4e9-83e84f1020b8","last_modified":1480349159069},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABKUXDqA8=","id":"e48f4383-6df1-0a9b-8063-a2add391a879","last_modified":1480349159034},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABLF5/Gog=","id":"bc0be7d5-b8d3-1ac2-8a63-f5bf8b00ba3c","last_modified":1480349159011},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"UW3oKZKTDsrPy/rfwmGNaQ==","id":"2a14bce1-47bb-e067-74a6-46be30e576a7","last_modified":1480349158980},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CSU=","id":"77e152ae-89a4-53b1-62d4-fb7c2cd5037b","last_modified":1480349158957},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"U3t2Vk8pfxTcaUPpIq0seQ==","id":"2c8f7191-fc5f-c2e0-af8d-852faefcdadf","last_modified":1480349158934},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:46Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABAPpuVh0=","id":"fce6cca1-707c-c4f2-6de2-26c4663cda01","last_modified":1480349158899},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"U4P1tUoxl/XkztlVHdtdgw==","id":"ed4d2530-eb3e-800f-41b2-e70023185673","last_modified":1480349158876},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEsMCoGA1UEAxMjU3ltYW50ZWMgQ2xhc3MgMyBFQ0MgMjU2IGJpdCBTU0wgQ0E=","serialNumber":"U3SgRR3J+D6575WuCxuXeQ==","id":"72e44e74-fb5d-fc97-abdd-02050d3ab727","last_modified":1480349158854},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJzdC1IYXJkd2FyZQ==","serialNumber":"EEpERSryZFMagbsNw/WoWQ==","id":"a4f11626-67e9-24e5-81a5-aca8126934c3","last_modified":1480349158820},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJQcQQN0=","id":"e7328f54-0f56-48a2-3bab-d4c9b41a2b13","last_modified":1480349158794},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydKkg==","id":"6b9bc0cc-c1fa-50eb-5ece-812ee9bac5b6","last_modified":1480349158772},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"cpqpXVWPk5AXzGw+zNIcBw==","id":"ac8d05cd-d85d-8caa-ed13-261b83c183c2","last_modified":1480349158750},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEbMBkGA1UEAxMSR2VvVHJ1c3QgRFYgU1NMIENB","serialNumber":"CWhp","id":"ff01b36d-3bcc-2157-1f89-b1841120c97e","last_modified":1480349158726},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCEUbthDurBjJw0/h/FfuNY","id":"2c047b2c-43aa-d0be-e2c9-2acac789bd55","last_modified":1480349158695},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==","serialNumber":"TXxtAQ==","id":"ea4847df-ca17-c476-11df-b14c1d6658a0","last_modified":1480349158671},{"schema":1552493039345,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1142137","who":".","why":".","name":"T-Systems intermediate cert","created":"2015-05-08T10:51:23Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpGcmF1bmhvZmVyMSEwHwYDVQQLExhGcmF1bmhvZmVyIENvcnBvcmF0ZSBQS0kxIDAeBgNVBAMTF0ZyYXVuaG9mZXIgUm9vdCBDQSAyMDA3","serialNumber":"YR3YYQAAAAAABA==","id":"ae8bec3c-3b92-822e-53f1-68394cbb1758","last_modified":1480349158647}]} \ No newline at end of file diff --git a/crypto/x509/revocation/mozilla/testdata/test_onecrl.json b/crypto/x509/revocation/mozilla/testdata/test_onecrl.json deleted file mode 100644 index d1bb320b337..00000000000 --- a/crypto/x509/revocation/mozilla/testdata/test_onecrl.json +++ /dev/null @@ -1 +0,0 @@ -{"data":[{"schema":1527680137883,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AQ8=","id":"c056f51e-560e-4386-ab51-aa1447c3f778","last_modified":1527680138898},{"schema":1527680136986,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARA=","id":"7e68e021-3514-4f54-bff4-16562a15fd8b","last_modified":1527680137878},{"schema":1527680136041,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARE=","id":"680e1552-a9c7-465b-9230-796fbaae08af","last_modified":1527680136981},{"schema":1527680135121,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATEz9w==","id":"95d4aa6a-e99d-4706-b071-b6c9d18f38f4","last_modified":1527680136034},{"schema":1527680134195,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"Q704nTrqxVY=","id":"1507de3d-b758-4803-8048-edaf5b747848","last_modified":1527680135116},{"schema":1527680133277,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMw==","serialNumber":"SMwb3p7dSlA=","id":"57ec979f-fa95-401a-8791-8adf2edd0223","last_modified":1527680134190},{"schema":1527680132398,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"XJI7ULS6xv8=","id":"56e35d02-2284-4f72-9dd2-8606c005b3e7","last_modified":1527680133272},{"schema":1527680131502,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"eNYPiDzOMtQ=","id":"d47cb30c-c61b-4514-9435-14998929b8e1","last_modified":1527680132390},{"schema":1527680130609,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJOTDEiMCAGA1UEChMZS1BOIENvcnBvcmF0ZSBNYXJrZXQgQi5WLjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE9MDsGA1UEAxM0S1BOIENvcnBvcmF0ZSBNYXJrZXQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"M9pDPXYgyiimYdML5Wg4zQ==","id":"ce3da6f2-bb52-4ea8-b2ca-334a49f34494","last_modified":1527680131497},{"schema":1527680129688,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"X407nWyYC7u8lCrBrW2cRA==","id":"3c05d750-a448-4a72-8fe6-337efe7b68f0","last_modified":1527680130603},{"schema":1527680128739,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"DmbpIZh1fhYcSThCcjaohA==","id":"e3c45873-f60c-4a04-be49-48e84b26c842","last_modified":1527680129682},{"schema":1527680127642,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"TpTE/3d2UBJYfYHw2LSoww==","id":"4c6efcb4-ab11-4ebc-a527-bb9d4b5d54a9","last_modified":1527680128734},{"schema":1527680126719,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"W9KDjZvaDeWwN4jQG9TO3w==","id":"4c841dba-55af-4fb2-ac56-9a4e9e090e9d","last_modified":1527680127636},{"schema":1527680125799,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"RWHsRyzP3KFyjhTLPO4FPA==","id":"49638a65-fc28-4f9f-bac5-618e2c4df184","last_modified":1527680126713},{"schema":1527680124874,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABECVWTJM=","id":"fafb930f-555d-4185-b11c-51542f67e9ed","last_modified":1527680125794},{"schema":1527680123970,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABI75RcWk=","id":"cb02a3fb-31a6-4e59-9b7b-298a675dcfaf","last_modified":1527680124869},{"schema":1527680123030,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABKkKSw14=","id":"ea62e720-34bf-43e3-863a-b920c4f9f3c0","last_modified":1527680123965},{"schema":1527680122110,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc3Cg==","id":"291cf8ea-ad61-4a25-a829-8444ab7ff3e0","last_modified":1527680123024},{"schema":1527680121193,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABSOXEgNk=","id":"a2b79aa8-7b05-43f2-8774-33be4e58e12a","last_modified":1527680122103},{"schema":1527680120273,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkw==","id":"e6b1307d-9179-4d0c-baf0-486fc60f9e3d","last_modified":1527680121187},{"schema":1527680119348,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"QHdGjRdEcAz+FjRyuIJmog==","id":"e7dd6129-27e9-43c3-832e-465f281653fd","last_modified":1527680120267},{"schema":1527680118428,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"JekvfVn3h2+OX/V8Ef6vpg==","id":"69975669-0ed8-4c98-8bfe-0179eca26f16","last_modified":1527680119342},{"schema":1527680117508,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"CHF76YGUdPMMCJ4njfsnwQ==","id":"f09d52b1-8a8b-4ca6-8d3e-aedcdfa2a2a2","last_modified":1527680118421},{"schema":1527680116482,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"OBGSpfa3Oz6a7zeF/OywMg==","id":"e8d4263a-45aa-4965-b66b-fff4c766fd35","last_modified":1527680117502},{"schema":1527680115354,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"deh5gFVej9+uQBqlb1fIig==","id":"496ee295-b927-4d33-9fd1-fc87b0327af5","last_modified":1527680116475},{"schema":1527680114434,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"aKsZrWDpsFlVL0xkShb22A==","id":"79eccf3a-91ef-4238-b579-373bbfc64546","last_modified":1527680115348},{"schema":1527680113509,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MHQxCzAJBgNVBAYTAkdCMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxGzAZBgNVBAMTEkJUIENsYXNzIDIgQ0EgLSBHMw==","serialNumber":"SFuFrFB7MZnZ6tsqwS47tw==","id":"b52359b1-3f41-4c09-bbfa-8b9e507ec567","last_modified":1527680114428},{"schema":1527680112694,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJkQ==","id":"783843ba-bada-4793-af9d-ba731980deb8","last_modified":1527680113504},{"schema":1527680111768,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byeekg==","id":"d8d6e770-d17f-4d6e-bbd9-e977a8b433d7","last_modified":1527680112688},{"schema":1527680110852,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekaw==","id":"7726f4b7-43ab-4446-82de-5b94436243ef","last_modified":1527680111761},{"schema":1527680109923,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpXg==","id":"fe0212f9-fd42-4659-8052-86a4c39e358c","last_modified":1527680110845},{"schema":1527680109003,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byekag==","id":"b86acd44-3dc4-4652-b48d-b0903b1ca74a","last_modified":1527680109917},{"schema":1527680108084,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpXw==","id":"c8acece6-3bd4-433f-ad93-ac379de4e8d7","last_modified":1527680108997},{"schema":1527680107224,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"Mi/Y+W40ChdUGpag8vaUjQ==","id":"9f89002a-a395-46a0-b050-e5f32733e807","last_modified":1527680108078},{"schema":1527680106344,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"eRdKqRQXNv4Vp8qfLP9FiA==","id":"1ad54d87-3100-49f5-8fd1-a156f5a479fd","last_modified":1527680107215},{"schema":1527680105426,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"EOqAPvgqxt8=","id":"5e5f0c19-5509-4c2d-96d4-7e89771a75ff","last_modified":1527680106336},{"schema":1527616725254,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1465399","who":"","why":"","name":"","created":"2018-05-30T12:35:03Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"amYSY2usyXU=","id":"0a3b7dd0-23ee-4ec6-8237-ceba9815e4ee","last_modified":1527680105419},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"KZlCQ0XnAo+GY3mKKJoNoNucjT0=","id":"b604fa72-f222-48f6-a8b7-8c7907a5b697","last_modified":1525201514127},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"JJfQeI7SQbQcPQ8Wc4+X2nlpWho=","id":"e5d6417c-1b43-45e0-a9d5-ccad984a9170","last_modified":1525201512695},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"bdheRp0SfvS84GGiPaBnyFhE8EY=","id":"8e9d1e04-962c-4495-89be-f25d3cd7d8d3","last_modified":1525201511157},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Z6RtH7xmDM0r66IKSlpCZNrlRfY=","id":"cc7d8a02-77da-415a-842b-83d2f60e1bf3","last_modified":1525201509729},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"VOQX5SLKeMGyQdoF0X9h38gYrks=","id":"d34174b6-22f9-47b4-af3f-7d78b2ce313f","last_modified":1525201508294},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE7Ow==","id":"6d27a296-13e2-4b53-880e-32f7030708a6","last_modified":1525201506960},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGAxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMTAvBgNVBAMMKFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBJbnRlcm1lZGlhaXIgQ0E=","serialNumber":"a5DOAqSUlLm2s6kL0x8gkQ==","id":"04216f09-9d99-4699-bf56-81cb74464d6e","last_modified":1525201505526},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"AeUotGv9K4mpvLzWxw==","id":"ac3d127c-2b79-4a52-94fa-b3ce9f420f2c","last_modified":1525201504399},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFI2MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"Ro51e1DpnjbH3LKdghY=","id":"e63eb91d-a23d-4f90-babb-9c4c2baf3da0","last_modified":1525201502761},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"R8MQVHZjYD/8LqGrob8=","id":"3264ae57-4d3d-482a-a169-f66652d93ff9","last_modified":1525201501429},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIx","serialNumber":"B6AKfwrKX6H1AAAAAAAAAAE=","id":"7647d289-2123-401d-b316-d84482d851a9","last_modified":1525201500273},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIy","serialNumber":"CMUHBBak0idMAAAAAAAAAAE=","id":"a792f002-d392-4bb5-ac92-94fe71853dbc","last_modified":1525201498941},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"GARMIB0Iaz3xxucE70O9Qg==","id":"dd5c26f0-c931-4d95-ade1-f243ba56a7eb","last_modified":1525201497640},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAktSMRMwEQYDVQQKEwpLRUNBLCBJbmMuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSIwIAYDVQQDExlDcm9zc0NlcnQgQ2xhc3MgMiBDQSAtIEcz","serialNumber":"fLpClvRi4IMKsokzVKT9Yg==","id":"2e3b108e-3455-44e3-b519-262869934aea","last_modified":1525201496208},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"JFcRHv1L89Vu8gagzuR3Pg==","id":"7732cbbc-9821-492e-8f1e-7b8754a1dc12","last_modified":1525201494877},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"CAEyq5GePgxvZbmFx5WW6A==","id":"5f6842bc-4062-4445-a442-17ec20539f59","last_modified":1525201493653},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAk1ZMR8wHQYDVQQKExZNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSowKAYDVQQDEyFNU0MgVHJ1c3RnYXRlLmNvbSBDbGFzcyAyIENBIC0gRzI=","serialNumber":"L3UnLdK9iz8XVM1rbm3tTw==","id":"f2d9c522-665c-4d09-b6c2-e0653ca8dc8e","last_modified":1525201492418},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAk1ZMSQwIgYDVQQKExtNU0MgVHJ1c3RnYXRlLmNvbSBTZG4uIEJoZC4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH01TQyBUcnVzdGdhdGUuY29tIENsYXNzIDIgQ0EtRzM=","serialNumber":"Q0dKwXPiEec83XZPgsQh+g==","id":"119dc8cc-5dde-4e71-aa7a-dd2058aaaced","last_modified":1525201490985},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"PpIe9Q1JUVu5nN/+4HWAoA==","id":"b06fa973-e8ef-4deb-8dd6-af1f306563b6","last_modified":1525201489551},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Baw9WIPUcpFvYe8bilTVVQ==","id":"3105cae8-2380-44c9-943b-62bb59978626","last_modified":1525201488149},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"CpSHXk6RnrLSRVVJhVZEWA==","id":"a91e0705-eaae-417a-8cf5-f990c819c96f","last_modified":1525201486895},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"Bxt4PMyN1f5tIXW8W62DhA==","id":"ef5a0861-7a80-4bef-8189-6b190481cd0f","last_modified":1525201485456},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"bcIU/gztAKdw8elgpRh2vA==","id":"451f9b8a-ce9e-4393-866c-2a62440afa7a","last_modified":1525201484131},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"U51Qij2xILJB29u2m4ePyw==","id":"5ae5d4d8-47cd-4519-86f0-9e764f1fd1ec","last_modified":1525201482589},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIGUMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxRTBDBgNVBAMTPFN5bWFudGVjIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNg==","serialNumber":"VedYmG4aoUcioKT467SDcg==","id":"5c06e662-9307-463e-bdb9-07abfd4f311d","last_modified":1525201481154},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"HkN+3VDzRBFAw/QQ6XZ2gA==","id":"d284e696-c47e-4f9f-97b0-610dc7313438","last_modified":1525201480132},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"XaqJA1pYkpSOSst7Hmcxew==","id":"78487925-3b88-480a-ba6b-1d5e139b1ec9","last_modified":1525201478595},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"cIHLIBl0M9N90NNjZwhwSA==","id":"289275cc-72e5-4d51-b4f1-07346c5e237e","last_modified":1525201477470},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"I+zjm9Bi1ZVKLF0R96thFQ==","id":"efd22973-74ee-4157-8ddf-057a44f23c03","last_modified":1525201475931},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMS0wKwYDVQQKEyRHZXRyb25pY3MgUGlua1JvY2NhZGUgTmVkZXJsYW5kIEIuVi4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxHTAbBgNVBAMTFEdldHJvbmljcyBDbGFzcyAyIENB","serialNumber":"MfSUS8xHwG64IFRIU5IHpw==","id":"9e57aa7e-ff8e-468f-98ed-562dd56eee71","last_modified":1525201474704},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMS0wKwYDVQQKEyRHZXRyb25pY3MgUGlua1JvY2NhZGUgTmVkZXJsYW5kIEIuVi4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxHTAbBgNVBAMTFEdldHJvbmljcyBDbGFzcyAyIENB","serialNumber":"VhmAg9gQ0IaL5+lKzrKYPQ==","id":"a801439e-c1b1-414f-acbb-16b5fe362389","last_modified":1525201473562},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAk5MMRkwFwYDVQQKExBLUE4gVGVsZWNvbSBCLlYuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMSEwHwYDVQQDExhLUE4gVGVsZWNvbSBCLlYuIENBIC0gRzI=","serialNumber":"I1kCCASG38Q8TKOJaqQtvQ==","id":"eca07c7f-1a9c-46f5-a61f-a9696f8bdd7a","last_modified":1525201472349},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MGwxCzAJBgNVBAYTAk5MMRkwFwYDVQQKExBLUE4gVGVsZWNvbSBCLlYuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMSEwHwYDVQQDExhLUE4gVGVsZWNvbSBCLlYuIENBIC0gRzI=","serialNumber":"W4sqXNfJgPC3aLKkcOxq9Q==","id":"eac5a645-3936-457a-8d93-f2d8acb71e1f","last_modified":1525201471502},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MHwxCzAJBgNVBAYTAk5MMSIwIAYDVQQKExlLUE4gQ29ycG9yYXRlIE1hcmtldCBCLlYuMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9LUE4gQ29ycG9yYXRlIE1hcmtldCBDbGFzcyAyIENB","serialNumber":"F6sWArGVJv7AwBSxbnnqaw==","id":"4a21fbd9-4b39-4d8c-b2c9-82ace310f9c7","last_modified":1525201470403},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"JY5zdgD/mG9A4oB/uzdSwQ==","id":"859ec3d1-70bd-417d-a3a1-bedc847fb4f3","last_modified":1525201469016},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"VBy0L8eIKnVUGpY97OXrkw==","id":"e5ef5cbb-45ad-4ffd-a2db-beb350b195a3","last_modified":1525201468162},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"c+6uFePfrahUGpXs8lhiTw==","id":"b93e70b2-98aa-44d3-a62a-4f3bb49f9966","last_modified":1525201467126},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"PZfTkwQ5Yio+HE2mvtFzDg==","id":"4d559aad-94e9-4240-93d2-054943a9f31a","last_modified":1525201466102},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHpMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxLjAsBgNVBAsTJVNlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8gRUNWLTExNjA0BgNVBAsTLVZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlckNJQy0xICAoYykwMzEhMB8GA1UECxMYR2VuZXJhbGl0YXQgZGUgQ2F0YWx1bnlhMRIwEAYDVQQDEwlFQy1HRU5DQVQ=","serialNumber":"b+8vFPRPzN8+HCEWmIwVNg==","id":"047fdabb-c9a2-4eb1-aaa7-469511a8f1db","last_modified":1525201464668},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIIBGDELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMTQwMgYDVQQHEytQYXNzYXRnZSBkZSBsYSBDb25jZXBjaW8gMTEgMDgwMDggQmFyY2Vsb25hMS4wLAYDVQQLEyVTZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvIEVDVi0yMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJDSUMtMiAoYykwMzEfMB0GA1UECxMWVW5pdmVyc2l0YXRzIGkgUmVjZXJjYTEOMAwGA1UEAxMFRUMtVVI=","serialNumber":"Y3QACu2RGYVJ6FAnJWZpHA==","id":"703b71d5-0bf4-4af5-885b-d5c2165f4062","last_modified":1525201463440},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"BqVfPLKBlSg/4Enn+TGdbA==","id":"f4e4fccb-6400-4fca-8557-849ba24afac1","last_modified":1525201462192},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"cEBA0P3KPBk/ojwnYepwzg==","id":"4c13fe3b-275e-4459-bb38-dc54bf6ba01d","last_modified":1525201460880},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"P0qUU7RhznNP6V9iGYbSbA==","id":"4f6b910c-64a4-4919-8ff5-c9fdd1f7d740","last_modified":1525201459447},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"W99Z2UuV5pFP6V8AYIwcVQ==","id":"66226a62-8d11-4442-8cd4-65279cdc08fa","last_modified":1525201458032},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"dfE2CNAy9IxP6VwZ2IU2cA==","id":"e4012675-11d8-4514-ba99-7a519d9f64c8","last_modified":1525201456987},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"IqW4gO46S81PjTpHBA7mUQ==","id":"54088505-0388-44e8-89f3-54dbeee3d2f5","last_modified":1525201455452},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHpMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxLjAsBgNVBAsMJVNlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8gRUNWLTExNjA0BgNVBAsMLVZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlckNJQy0xICAoYykwMzEhMB8GA1UECwwYR2VuZXJhbGl0YXQgZGUgQ2F0YWx1bnlhMRIwEAYDVQQDDAlFQy1HRU5DQVQ=","serialNumber":"On0bAstcoxZP6WERe150Gw==","id":"d2241dbd-e9df-420f-ba92-0c9c9d8d89f6","last_modified":1525201454025},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIIBGDELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMTQwMgYDVQQHEytQYXNzYXRnZSBkZSBsYSBDb25jZXBjaW8gMTEgMDgwMDggQmFyY2Vsb25hMS4wLAYDVQQLEyVTZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvIEVDVi0yMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJDSUMtMiAoYykwMzEfMB0GA1UECxMWVW5pdmVyc2l0YXRzIGkgUmVjZXJjYTEOMAwGA1UEAxMFRUMtVVI=","serialNumber":"JSPC8hAKsUBP6Y3n9JMx8w==","id":"a6240c29-985b-41aa-bfef-a4b5b10c43c4","last_modified":1525201452790},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UECgwyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsMH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsMLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLDCxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAwwGRUMtQUND","serialNumber":"L5tOVjVGKtFP6V84tGEFPg==","id":"7780f12e-5f2c-4382-aa26-25e0b06e2a23","last_modified":1525201451667},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MIHzMQswCQYDVQQGEwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND","serialNumber":"IL094GkEPSU+HAucglL0Ig==","id":"b9db725d-2c89-42ad-8b0b-807311d0a5cb","last_modified":1525201450130},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEgMB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAyIFJvb3QgQ0E=","serialNumber":"KA==","id":"3d04d4fa-8dea-49f3-a47c-71e1443a9136","last_modified":1525201448898},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"UzAV4JqeuGY=","id":"8e357bb0-7738-4fb6-be98-1c3b0f34b883","last_modified":1525201447362},{"schema":1525201444709,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"bYuYcMtVvjo=","id":"3546a52d-6e2a-4f79-bfda-3c7514eaf39e","last_modified":1525201446066},{"schema":1525117300427,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1458321","who":"","why":"","name":"","created":"2018-05-01T20:04:01Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"WV2iHxGL6Vg=","id":"7aee1756-65b5-44d6-b368-bf7345dfb4d9","last_modified":1525201444699},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4af5Q==","id":"6d5c851b-0161-406e-8d63-8d3db27ca4f8","last_modified":1521539068414},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4b2Vg==","id":"bfd98186-8469-4f90-9caa-ef94ee7e5793","last_modified":1521539067480},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Hl7MT7aU4GbuanaMzc5eAg==","id":"b5d0f6f8-dc6c-42e6-86e3-db86c0f0ef3e","last_modified":1521539066546},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TrUuR7x7VeU7Qvlwt8Sumw==","id":"cd97a51f-ecd0-4cd0-afac-022a5deae387","last_modified":1521539065613},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ajUDfjuO76YmIt3+fyTLXg==","id":"6562ca7d-c4df-4c31-93b9-4a4ed561f830","last_modified":1521539064682},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"G0UY3ZCa+JfTgAVgvFA8qg==","id":"f31c2c71-e3dc-4f33-a12b-fad7aa9e1b66","last_modified":1521539063753},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dtULH8kD2mThpR/g1YJEtw==","id":"690c5b1d-ff08-4827-b7fe-0b43f8363202","last_modified":1521539062819},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"c5EZjjNc7LMOapbOzjEtJA==","id":"bcd2807e-15df-4eba-be88-2677fd17496e","last_modified":1521539061889},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dn2My7LvPi25AtUw3aPEmQ==","id":"1841b57b-5085-4ffd-9b5a-192ed098c6af","last_modified":1521539060941},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Qk03giZwJwxf5QpixTKflQ==","id":"01c7e0fd-4973-44d4-829a-896db0c7e1dd","last_modified":1521539060008},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"cepjeevcJiJnbGEvdJE1jg==","id":"e27659bd-3699-4eea-afb0-a435dfac9bd1","last_modified":1521539059082},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"BtDaTXIs6tBSClhSLPXdYg==","id":"33f91455-1f4c-4fd7-aeea-c7f1df9309fd","last_modified":1521539058135},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ej2u88yEVXEb8BP1K49U6Q==","id":"af65bc77-69b0-4afb-9451-b8ae0bcc7b62","last_modified":1521539057196},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"H/Vx9uatDIulnLLrZjXEKg==","id":"d1b51a6b-bcb0-44d0-830c-394a409c3fa0","last_modified":1521539056260},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"PxYWUib8jdriX5MSGW7Ozw==","id":"b8304b34-1fcb-46bd-ac88-796748e0278f","last_modified":1521539055332},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"T3UrJ2tKvT0lyumu37ic6g==","id":"629d62ec-34c0-466d-b9ec-4f1991f45ac4","last_modified":1521539054393},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"And3HzRA33dI3K772oqBCw==","id":"e7cea443-749b-48c0-90e4-72139c44b9a7","last_modified":1521539053460},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"ZpLTr9toPH+XRF7OITitfw==","id":"8e977340-0255-432f-a74f-b45f1d892f59","last_modified":1521539052528},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TpyAwu1JmlIKD9gyf+0d4w==","id":"86c1352b-e5e8-4e7e-9a88-ea8916d08ded","last_modified":1521539051596},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"A09gcxt2IBLNzwqUBAhkDg==","id":"bd99f32d-02fb-4a46-9265-8bdcb343b8f8","last_modified":1521539047661},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"dgkExobSurPQq8GYrxxluA==","id":"190e2d0d-35d1-47b4-8b07-73df5c649ba4","last_modified":1521539046709},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"UJ3tpbZLsyrhh60M9CMQaQ==","id":"b4c69adc-2247-4aed-8cb9-e0fd1bd4e457","last_modified":1521539045779},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"MpG5djdbcIoI5TIkJ7vENA==","id":"c2b676e2-f636-4489-ad39-ceadad4d122c","last_modified":1521539044827},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"BlOMLY2hk1OPGflbt/pPXQ==","id":"06096001-fd68-4d0e-be8d-832c24695c75","last_modified":1521539043891},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"APy7Z8kyJRVBcM/oki5xZ2M=","id":"71a73415-ba8f-4281-86b4-76311c2f0410","last_modified":1521539042956},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"ANjIV8rkvmb5E3Wf3aPV2ys=","id":"ca2547dd-66ec-4991-ab40-362581ebdc69","last_modified":1521539042013},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"AKbcLtOIMMwDPSOrzrclZL8=","id":"f463f5b3-b729-4da8-afc0-c54e54d857bc","last_modified":1521539041071},{"schema":1521539039181,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"BQ==","id":"821bc34c-45ce-444a-b7c0-0a581a788a52","last_modified":1521539040133},{"schema":1521488498637,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1447252","who":"","why":"","name":"","created":"2018-03-20T09:43:57Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"Ag==","id":"490cb9c4-e092-4200-9e4b-be790d4db9b6","last_modified":1521539039175},{"schema":1518550896180,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1436524","who":"wthayer@mozilla.com","why":"key compromise","name":"","created":"2018-02-13T20:30:40Z"},"enabled":true,"issuerName":"MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMSAwHgYDVQQDExd0aGF3dGUgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"dqN9ZZM/PfFCXStajJdbtQ==","id":"1dea3a27-cf12-440c-b77d-08608dcb4fae","last_modified":1518553957211},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"IsWDgJMv7uY=","id":"6252eb0e-d613-4290-a7ab-1b6698146077","last_modified":1518185155027},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"WDFms0iypljMkohTzBvf4GmTOu0=","id":"938ea097-b56a-4286-9370-a1dabb46c908","last_modified":1518185154165},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzM=","serialNumber":"PybG62jqpxKYOV5MlXAGPJYDy9M=","id":"495b31a1-84f2-4a2e-b4b0-f24303c0b114","last_modified":1518185153363},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SsQ==","id":"5373d63b-fdb3-4cf2-82c4-6d5dde47a536","last_modified":1518185152542},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATEzEQ==","id":"e0589829-384d-4cd8-952f-3b4d5b3116f0","last_modified":1518185151698},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE33w==","id":"b4208886-7ca1-4d3f-a6b7-271f93aaf6cd","last_modified":1518185150862},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byecpw==","id":"0a419007-294d-4c7e-8ae4-e26c83633f5a","last_modified":1518185150011},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHoxCzAJBgNVBAYTAkFVMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazErMCkGA1UEAxMiU3ltYW50ZWMgQXVzdHJhbGlhIENsYXNzIDIgQ0EgLSBHMg==","serialNumber":"MZNwCx0BAjzTOgcvHsmdhQ==","id":"f7ee0207-7809-4310-a334-906a783c94f9","last_modified":1518185149162},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"PWwhjEHh0n5G6P8b+bAkcg==","id":"8ed4a6a5-4222-44bd-b52a-2fc5b2093fd4","last_modified":1518185148285},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye/xA==","id":"49f10bd9-4827-42f8-b6bb-1136cdb8b1f1","last_modified":1518185147458},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkFVMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEmMCQGA1UEAxMdU3ltYW50ZWMgQXVzdHJhbGlhIENsYXNzIDIgQ0E=","serialNumber":"Nn6RHaVImMEtHLbPqlyGEA==","id":"49216c75-cdfa-423a-84cb-a4285e9efc65","last_modified":1518185146632},{"schema":1518185144959,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"X22XOlwfc1Taw/ORwGOIeg==","id":"21e8b448-bdc3-4549-8436-7b5218662f7b","last_modified":1518185145800},{"schema":1518126030238,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1437038","who":"","why":"","name":"","created":"2018-02-09T14:05:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"PgImeGqCkapG6P426Ne85w==","id":"9c7330f0-ac62-44f6-9ecc-1f6c8090e22c","last_modified":1518185144953},{"schema":1517320853622,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1433118","who":"jc@mozilla.com","why":"key compromise","name":"","created":"2018-01-30T17:48:22Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSkwJwYDVQQDEyBDZXJ0dW0gRG9tYWluIFZhbGlkYXRpb24gQ0EgU0hBMg==","serialNumber":"VEav0UR+l38TpKTRi7sS1g==","id":"cb712a6d-3b3d-4642-b0f0-5f765f615559","last_modified":1517334651604},{"schema":1516714880468,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye9zg==","id":"fead3048-84a5-4256-9850-cf412c8cce88","last_modified":1516714883099},{"schema":1516714880468,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeWyA==","id":"5d178546-44d0-4756-8bc1-aa84c958ec6d","last_modified":1516714882194},{"schema":1516714880468,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1432467","who":"","why":"","name":"","created":"2018-01-23T13:41:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye9zw==","id":"ce6dc2f0-5709-49d6-a762-87e297e2c4f3","last_modified":1516714881354},{"schema":1516650097396,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1427034","who":"mgoodwin@mozilla.com","why":"","name":"key compromise","created":"2018-01-17T13:03:45.551668672Z"},"enabled":true,"issuerName":"MHAxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xLzAtBgNVBAMTJkRpZ2lDZXJ0IFNIQTIgSGlnaCBBc3N1cmFuY2UgU2VydmVyIENB","serialNumber":"Cn+uUpLudsH09lYYIPTK5A==","id":"37450b9d-89e2-4144-af21-c01dfb50d5e8","last_modified":1516714880459},{"schema":1516131690774,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430498","who":"jc@mozilla.com","why":"","name":"registry problem","created":"2018-01-17T00:30:37.551668672Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"AJk3QFH13eHUHHVnsvwS0Vo=","id":"c3485d18-5309-46f4-a324-b72aae76d2fa","last_modified":1516150019120},{"schema":1515958890786,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430498","who":"jc@mozilla.com","why":"","name":"registry problem - remove after Feb 2018","created":"2018-01-16T14:26:03.648712626Z"},"enabled":true,"issuerName":"MHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEQMA4GA1UEBxMHSG91c3RvbjEVMBMGA1UEChMMY1BhbmVsLCBJbmMuMS0wKwYDVQQDEyRjUGFuZWwsIEluYy4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"NlLRZJFLco/An3cLAGjGgQ==","id":"ee550d4f-2e5e-4a92-84a0-97595775682d","last_modified":1516119227966},{"schema":1515779172012,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1430172","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:24:38.732932137Z"},"enabled":true,"issuerName":"MIGSMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE4MDYGA1UEAxMvQ09NT0RPIFJTQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0E=","serialNumber":"TasC8Zd8BT8kXEE67cFQmA==","id":"fd5a2c90-20dc-49fa-8d98-4ce4f75a9e67","last_modified":1515779270416},{"schema":1515773559405,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1425376","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:10:12.532698105Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"UDE/uwr4z5V8eZI4+1gkAw==","id":"c848badb-926d-4a4b-84ca-776d8e83afbd","last_modified":1515773559723},{"schema":1515767582106,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429636","who":"jc@mozilla.com","why":"","name":"key compromise","created":"2018-01-12T16:07:30.989396006Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExGjAYBgNVBAoTEUludGVsIENvcnBvcmF0aW9uMSUwIwYDVQQDExxJbnRlbCBFeHRlcm5hbCBJc3N1aW5nIENBIDZC","serialNumber":"HwAABsvzDP+DIzUG6QAAAAAGyw==","id":"754959ef-52da-40c2-9f01-6d58cee4bb6e","last_modified":1515773559394},{"schema":1515506201315,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFQxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVkMSowKAYDVQQDDCFRdW9WYWRpcyBFbnRlcnByaXNlIFRydXN0IENBIDIgRzM=","serialNumber":"bqapwACCtKhVagTl7cEP7KFbM0E=","id":"557dce95-1f9d-4292-b0e3-1e6190ceb6b2","last_modified":1515506204155},{"schema":1515506201315,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"BFA=","id":"8b5b2498-3bda-404a-b778-8231f31548ed","last_modified":1515506203323},{"schema":1515506201315,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNbw==","id":"54bc1bfd-3c57-4698-9702-bf18862330e5","last_modified":1515506202308},{"schema":1515440499630,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1429055","who":"","why":"","name":"","created":"2018-01-09T13:56:39Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"Eg==","id":"bc46d429-2528-4068-b205-b0f853e3865b","last_modified":1515506201306},{"schema":1513194091216,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1425166","who":"jc@mozilla.com","why":".","name":"key compromise","created":"2017-12-14T17:17:08.723413Z"},"enabled":true,"issuerName":"MIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcy","serialNumber":"AOfHzdPzlvw5","id":"47a94296-eb80-4f80-a327-d6c0dcf96e83","last_modified":1513273512012},{"schema":1512596194460,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423400","who":"mgoodwin","why":"Added per CA request","name":"Microsoft IT SSL SHA2 revocation 2","created":"2017-12-06T16:51:03Z"},"enabled":true,"issuerName":"MIGLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMRUwEwYDVQQLEwxNaWNyb3NvZnQgSVQxHjAcBgNVBAMTFU1pY3Jvc29mdCBJVCBTU0wgU0hBMg==","serialNumber":"WgAFElbyxxPA8BdM4gABAAUSVg==","id":"41d101d3-2258-4c62-94b4-288e140a4205","last_modified":1512596195433},{"schema":1512488575227,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423400","who":"mgoodwin","why":"Added per CA request","name":"Microsoft IT SSL SHA2 revocation 1","created":"2017-12-06T16:51:03Z"},"enabled":true,"issuerName":"MIGLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMRUwEwYDVQQLEwxNaWNyb3NvZnQgSVQxHjAcBgNVBAMTFU1pY3Jvc29mdCBJVCBTU0wgU0hBMg==","serialNumber":"WgAFElcDxFjoswSzjAABAAUSVw==","id":"d6e37caf-2691-4a82-8682-72b454419d8c","last_modified":1512596194454},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"em/HTY01Cvv6ITgkH+ftlg==","id":"7b48e485-3f00-4838-98d7-78c731f014e7","last_modified":1512488574225},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"a2GKnRbYMZ0oZkRzJE8NIw==","id":"0efe9970-3656-4aa9-8fd2-cfe290ca2c7e","last_modified":1512488573423},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"QspbHxzWb41SX9TUhF1N1A==","id":"bb2d8dfc-6dd0-47c3-a46c-c0f8235418a4","last_modified":1512488572398},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"PbXdgANzAyCOCZ5qa/7E6A==","id":"f3f7d94c-c3d6-48f1-b807-43c97784dcdc","last_modified":1512488571476},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EgtJ1f+/tZwlGfg0Uu7XCQ==","id":"331b24c7-b0dd-4289-9ef7-a4f92eb4f449","last_modified":1512488570451},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"TbPyD9NnsEcxyK6LIsr78g==","id":"eb7bda20-89d0-4ed5-a731-0896127de01e","last_modified":1512488569530},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"JjjcXrfGjTCi1ug/AEeYlg==","id":"0f7d3bf7-ddeb-4c1b-ba24-7ae9157bba15","last_modified":1512488568584},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"HGD2RtvXMaPDqHIPLdXocw==","id":"b26128cc-3096-438e-858f-7c2cbaf3c903","last_modified":1512488567585},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"fa9agGguMHfBorMTXXMd9g==","id":"2ace54b8-3856-4aa9-bd26-45f573e737ce","last_modified":1512488566638},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"WfPUsnnSF04ShWVYEa/KRA==","id":"5bc1d739-7788-4f13-b92c-5b6a8662319b","last_modified":1512488565741},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"LzVYePklc3vH3jkk0BZr9g==","id":"bc7eea97-3ee7-49a0-80a7-c0f1a346a1c4","last_modified":1512488564721},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"BWuckD4dPHZYW5ThBsl+aQ==","id":"2a474462-256d-4583-9103-297077b85bad","last_modified":1512488563751},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"LJ8wKbrQXgT8VExZ6vEfWA==","id":"4a1c1053-a8a9-42ff-bb3e-3ac5c536d5c3","last_modified":1512488562853},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"GskXrIFkzLS+4yohQM9EUA==","id":"a3b8a885-9d36-483c-8b4c-c80e8795bb92","last_modified":1512488561945},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"X3iUdzxCEtOAKpiTLsqjBA==","id":"7fc162c0-b668-4336-ad9a-cf6ac4bf7f88","last_modified":1512488560934},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"UKM/CNF2OvC4giYnAUG/Ag==","id":"7f8575f4-dcd7-4e51-9540-674ea52a0afc","last_modified":1512488559917},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"fZ10MyCe51jAjZCsDgqaxA==","id":"a943a2dc-e783-4560-90ec-5b2ce4936f60","last_modified":1512488558952},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"Gz4uHrL2usrTZrPCHeuF5g==","id":"cf84a41a-afeb-4727-b51e-f1489075f5a0","last_modified":1512488557959},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"bf8hEJywo1lAp4UNcLl5Ew==","id":"26c0ae81-c15c-4f37-930c-f3c39fca709a","last_modified":1512488557038},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"P4sUnc++hlU/bXj0zSTlcQ==","id":"1a68fa22-b801-4f56-81b2-a6575dd928ac","last_modified":1512488556115},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KUZMXOUj2sdY2i2Rfgp/5Q==","id":"4c1f25cc-e17b-4ce4-a0c8-ab871a370238","last_modified":1512488555092},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"a9HDb1beqQYmkvFH0qExcg==","id":"b876cede-af38-44ff-952b-cf1652e0eff4","last_modified":1512488554136},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"C2tQZWb2eoQD2XC3F5JSzg==","id":"67c163b1-7be2-434d-9a17-24ab282e0906","last_modified":1512488553221},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"QjiuX0y1agXQQqmDB2yh3w==","id":"966bf4c9-229d-40ea-8783-cdd20a90e7d0","last_modified":1512488552326},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"YwslVqGwc9CHkaZkXNZ4xw==","id":"e35a9cd7-72a9-44b6-bb42-c43054e279d3","last_modified":1512488551279},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KRfQOuBdOSpEmAxSpDZGZg==","id":"3901e046-eee7-462e-9207-62a2074d5555","last_modified":1512488550258},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"IARKrBjlKQLyVGA4X52L7w==","id":"59872bbc-66b1-4627-890b-b8e9aee46d08","last_modified":1512488549244},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"TsaDDThhoyhX10SURO3NMg==","id":"477a1238-b526-4dbf-9e7d-8807315f8e5a","last_modified":1512488548206},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"dSBsq/te0hzZauKHgJ3EWg==","id":"320c2435-4a3d-4a9c-898e-0be3e7314601","last_modified":1512488547208},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"JLLEdDl2iHqqyenVWwQ/XA==","id":"d1d33ccd-4ea7-4b1f-9969-b77036da72c0","last_modified":1512488546183},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"D4dSwi4udjGtMftKLTSFyg==","id":"36e0661b-bbce-412d-b181-f51599b5133f","last_modified":1512488545212},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltmw=","id":"7ab02aa8-9300-4e05-bd35-1a8a0dc66114","last_modified":1512488544217},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm8=","id":"3128a9a7-5929-495d-b6e9-d1322d8969cc","last_modified":1512488543316},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"N4XreFRrqFQ=","id":"0cf09345-c803-4248-8e8f-4fd437efc225","last_modified":1512488542191},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"Ah69dEvrzT4=","id":"eabda172-8673-4d9d-b955-ae33491273d0","last_modified":1512488541251},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4","serialNumber":"RXJFI0h6EJY=","id":"0ac03d6a-f013-45f1-a611-8d408d81cda2","last_modified":1512488540265},{"schema":1512488538210,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290","serialNumber":"DA==","id":"8374c965-72aa-4411-96a9-d0ed94b6eff5","last_modified":1512488539210},{"schema":1512330096754,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1423239","who":"","why":"","name":"","created":"2017-12-05T15:42:15Z"},"enabled":true,"issuerName":"MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==","serialNumber":"AklaZYwhC9k=","id":"0ef6e97e-f104-472f-a639-f5095bee2cec","last_modified":1512488538203},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGcMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0x","serialNumber":"APB/jQRgyP8Q","id":"89031d16-d554-432c-b874-29611e57ddc7","last_modified":1511530774264},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"AOVojQRgyPcY","id":"365afa37-c1b7-49a1-b426-3ad6f41062ce","last_modified":1511530773342},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTI=","serialNumber":"APB/jQRgyPca","id":"469dc3f7-856e-46e9-bcd4-4690669a1164","last_modified":1511530772420},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTE=","serialNumber":"AOVojQRgyPca","id":"350ab323-afb6-4b13-ad9d-4fd751b43b6d","last_modified":1511530771603},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"OeKv0wi+ATDxfQ6CWir1vA==","id":"f9cdfe8d-8646-4f51-a52e-2f8e207dd9af","last_modified":1511530770270},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"VNb2Hjai/t7dmCtOzRXXew==","id":"58ff4957-a4c8-490b-8ed2-28ec1730c0e5","last_modified":1511530769350},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"CuUEKEJM4xhxlFXraPcSpQ==","id":"7601c888-8cc4-4c4a-a1f8-c7035f722d59","last_modified":1511530768331},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"FK+rVRFA0o0PnW+X6V60gQ==","id":"94b0d239-ef85-46fd-8af6-4213e19bbe5a","last_modified":1511530767405},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"UT6GtTGbEC6SXJteWAKy2g==","id":"f232a4f0-ab91-4cde-acd6-28745c3c2bd0","last_modified":1511530766483},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"c0ENPRDbRozjU83garZrdA==","id":"5c07893e-ed64-43c5-aabb-fd7d059100f6","last_modified":1511530765531},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"ODTGURr0vY14WkIt15hHrg==","id":"26b8bba0-1be3-4f66-98d3-936a13c810b8","last_modified":1511530764744},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"RkNUwM80Jt7beb4ek+iI8w==","id":"e28af90b-6ca1-4335-876b-4afedaea6cf8","last_modified":1511530763884},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"dUIqmrcgq/261bRbo7fM1g==","id":"6d8170da-8177-4e04-988b-e24f36c39001","last_modified":1511530762701},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"XbPH0u4MjoIrWzN8QCilfg==","id":"a44b3f08-cbb8-4fbe-98c0-e7710dd3e81e","last_modified":1511530761466},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"KvQ5AzK6tQy8eBy7NAD/lQ==","id":"882fa317-43a7-4515-b79b-437119b72cf3","last_modified":1511530760452},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"UfM8pWkcmmLGRiGIVydmoA==","id":"069856d2-6bd0-4b39-a8f5-2debd4535542","last_modified":1511530759416},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"X4C5SJIG0BDeJvpQq4ngCw==","id":"9abf8a9e-66d2-4193-9dd8-3d86f482d44f","last_modified":1511530758551},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"CGo/+42e75JBJ2JcOEaMFw==","id":"879c2baf-c634-45eb-b80b-c1fb0ceb31d9","last_modified":1511530757370},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"Q1r0dRkkG9miuHj/Y52izw==","id":"9e9ecf02-4c1c-4c32-b10a-c7272c416b5f","last_modified":1511530756553},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"WU+jmMhGAumhewqVKrZBmg==","id":"27bf3c0e-8868-4274-b37c-b3a4bde99ba1","last_modified":1511530755428},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"d8ToN4Dfs5RqD2yfAp12yQ==","id":"972f597f-5333-4ec4-8801-751bb5546abe","last_modified":1511530754297},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"ElBUYv/f+6+gnbAJ23qnAA==","id":"6ad92631-7061-4717-93ed-b5f56d8452b1","last_modified":1511530753374},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"DoP7aSdEs/3y+o2Gj9zgWA==","id":"16737b7d-6e89-43d1-8a4a-0f1a931371f8","last_modified":1511530752482},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"XOZMbPKQuJEw8Ib5neDVpQ==","id":"6d117cdb-5081-48b0-8408-4ca74edb943e","last_modified":1511530751226},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"UN78HLEKf7W9vQYkzYpJnw==","id":"e52276ca-6055-4069-8277-e046a6c8dca1","last_modified":1511530750302},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"KNhgX8XuJduYciIyatpOQg==","id":"000e9e4e-75dd-46f1-8acc-acdb9844a1ba","last_modified":1511530749075},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"OIJdAvYxHmLb6YaaMmwmjg==","id":"b2085d97-60ab-449c-ad46-8ca2818da916","last_modified":1511530747846},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"SrQ125q7UcLfxVKepx+lRg==","id":"5b2d0011-e159-4fe2-8d40-72fd5c210474","last_modified":1511530746840},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EYfoVrySx7V3OUqs4xKvgA==","id":"39bf9bb4-2301-4d71-8c46-7a88f5b0cbae","last_modified":1511530745816},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBFQ0MgUm9vdCAtIEcx","serialNumber":"EkoaKijVTGVYI5c604iweg==","id":"eb900242-3154-40c3-8f90-391c5c15a6d5","last_modified":1511530744778},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEnMCUGA1UEAxMeU3ltYW50ZWMgV2ViIFBLSSBSU0EgUm9vdCAtIEcx","serialNumber":"VIFPnH3Io2OmF0J5KK8gzA==","id":"0aa3a176-7080-48d4-b8f2-8a3c60a6de88","last_modified":1511530743731},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"ANsAyDuSSs7Z83LfMZ+TDw==","id":"f20c25eb-a06f-43ac-a202-710565679819","last_modified":1511530742622},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIQ8dLGqNIaxxMeg31W16Q==","id":"aec665a0-9d68-4342-9743-18efc713e0f8","last_modified":1511530741394},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIQ8dLGqNIaxxMeg31W16Q==","id":"8a10108d-b91c-49da-9748-72421d965126","last_modified":1511530740428},{"schema":1511530738037,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"cFbYT3bxd1sAAAAAUdNX8A==","id":"892f7600-cbf9-41d7-8854-91e39cca6d64","last_modified":1511530739059},{"schema":1511466096308,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1420411","who":"","why":"","name":"","created":"2017-11-24T13:38:55Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DNHqTQd9QC+JnMy6AWyhkg==","id":"8f08f0c9-78a0-46cf-ac37-4d272b696046","last_modified":1511530738030},{"schema":1509910896392,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-02T22:09:46Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AxPlMqxkByCn3XNuYMhYNMcp","id":"eab2fa01-c3d4-4fd1-b3b8-9d88ed9b6657","last_modified":1509980661621},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723413Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BPVqx4UbKVAbJSFTKwrcFryU","id":"f644b647-a845-40ef-9f6c-36744f304d08","last_modified":1509744817871},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723410Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOncXh7IZp1SNydhtUdyh2O2","id":"58e3d1dd-4602-4b04-9f99-3f6efe1b0653","last_modified":1509744808464},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723407Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOc11keA9WJ9R20XQY8hO7yi","id":"749a02fe-2f0d-4eeb-84ff-f2730ec10bdf","last_modified":1509744807487},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723405Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOPwjyn5eqfeoxs7Z0y3vqNN","id":"9bcd94b9-c798-43da-9520-f15ffd3418e8","last_modified":1509744806955},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723402Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BONHqLIx/ibQE08IQIyoGaXg","id":"1b719105-db02-4597-8d5e-4e60a72167dc","last_modified":1509744802604},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723398Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BOIIipysxAz5xHIMmFRvYchY","id":"6f43ef92-37ea-407d-b113-0d1a2f30af6d","last_modified":1509744793918},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723395Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BLlQHJ611eOZuedFrFgVAfAs","id":"af6370dc-0ee2-4f46-864b-4aba6dad16aa","last_modified":1509744793363},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723392Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BKrxi2/1iFxHEFzyZvegxq5C","id":"8636eb93-74a1-4a6a-9fbe-c027fce6e1f3","last_modified":1509744792878},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723390Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BKobzjrOxa/6kCR0ImKoqaQW","id":"87cdeef4-a32f-4f89-90b2-d979766f66fd","last_modified":1509744792287},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723387Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BJDHnthjoDRutxFRJPFnixbU","id":"fd062b35-a923-4f40-adb6-b438b21dcebb","last_modified":1509744791739},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723385Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BHT6CK6B569m/dd5dEluBOEd","id":"dbd760d1-545a-4c22-9634-8266b173fea7","last_modified":1509744791182},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723382Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"BDV89QWZE9MJYlCpFQUv5Y2W","id":"5933c583-8b53-41b9-a23d-3fa849a39f22","last_modified":1509744790658},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723376Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A/99bZCzSpexYL5y6dSryDn3","id":"62a22818-bb50-4f99-ae28-194943003e28","last_modified":1509744790097},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723373Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A/7DHCczBnP5qUVh0jF2pvwB","id":"930fdbad-652c-445a-be30-1721420d5308","last_modified":1509744789472},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723371Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A+ly3y1rVP59k/MKfcE3DoEq","id":"2be75058-2815-46b4-97de-5f800fac23fb","last_modified":1509744776797},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723368Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A+RCQYwhofmXM+/hxdyoUzkI","id":"ece94a68-9224-462d-aa7d-174e461c3eac","last_modified":1509744776283},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723366Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A9BRwOwbXRRhCe+kcmglgW3z","id":"b17c537a-31c2-4547-90a7-5588e967e0d2","last_modified":1509744775761},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723363Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8wZnhfuY6VIV1SwGsTGNR7L","id":"06dd2b87-9f23-4ecf-a6d7-1c4e248c377d","last_modified":1509744775215},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723361Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8aDg1/IA4O8gjMPZHVqPI+w","id":"e90d77e0-1e41-4a45-9c4b-a0b615b0091d","last_modified":1509744774659},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723358Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A8LV4zckxcwdttbQSk0EPnoA","id":"421f4d83-9377-403a-b28b-c7249634e7fc","last_modified":1509744774150},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723356Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7uy+rmTav6tDH4dRrsnvXGH","id":"188d1c6c-c94c-4a1a-8028-cbc7c29069d4","last_modified":1509744773593},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723353Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7T0V6o47rgCKl3oUb7jF2Ph","id":"fee8894c-8624-41fc-ae9a-7180f52714f1","last_modified":1509744773026},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723350Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7RCxMe1S9Hb7ENzRxl0mxGP","id":"fca062d6-5292-4ca1-87ce-a6aa34c6a1ae","last_modified":1509744772514},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723348Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A7GX+szdK8/7Kf0xUuarfyIN","id":"fcaebe3c-564b-46c0-a852-a6e51d8a56cf","last_modified":1509744771973},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723345Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A5oET6WBWx72ColKf0txoWyR","id":"b6cd6dd6-4173-4584-ad06-d3a6400f4c4c","last_modified":1509744771414},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723342Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3ZQibPGSZ8nPVbuccaCvUfa","id":"c67ca525-ccdb-4ef9-8029-422656cbdbc8","last_modified":1509744766044},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723340Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3WVy2V+2VFkWtMvA6HFwnhq","id":"69b9dc1c-9178-4090-82d2-4ecb650bf8a6","last_modified":1509744762617},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723337Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3UNTBOHUkbq+k999nJeSJdF","id":"12f76ac6-cb54-42d2-90e2-a06fbf6cc681","last_modified":1509744758183},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723335Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A3TWA5Aylxw0x8bVvrmUSNJd","id":"6765cc1a-15e0-46e8-b74a-30a03f538885","last_modified":1509744757639},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723332Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A1V4dX0tTb1rdTZxdWcuZ7YR","id":"fddf483c-b881-4a58-a24c-03b0f46ca701","last_modified":1509744754400},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723329Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"A0BOaf9UbJxzqBudSyes/cEM","id":"21c2287c-c873-4a06-bd80-8c2498deee0c","last_modified":1509744746034},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723327Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AzL4tLuklekJ8lSh6VnRMSrk","id":"fe19f480-7306-4eb4-a434-bb21e983102e","last_modified":1509744744506},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723324Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AyjNQ4dnGD3FD6WL5gYrYru7","id":"22ef2da0-8e63-40fe-8644-667178538911","last_modified":1509744743907},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723321Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AyYMguSo1my449OZq51C3s3Z","id":"bbb3fb02-ff86-44d0-859b-9b827c4943ad","last_modified":1509744743316},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723318Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"Ax6Jm7ajV49tqHgf9nYnzRCI","id":"f2b5d0ef-312b-4de2-9cd6-e0fb9bf262df","last_modified":1509744742729},{"schema":1509744741590,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723315Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AxW0+uDsfyCSfhECdsGGpVD8","id":"0266840c-ce0c-47c1-8816-2c4f4b29b3f4","last_modified":1509744742199},{"schema":1509738096737,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1414039","who":"jc@mozilla.com","why":".","name":"registry problems - remove in Feb 2018","created":"2017-11-03T20:43:04.723168Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==","serialNumber":"AwBGo0Zmp6KRryAguuMvXATI","id":"d5c21685-054a-4233-a633-0af3d769b0e7","last_modified":1509744741583},{"schema":1507714023132,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARU=","id":"b91f4d33-972a-42ab-859f-0d3c8b68efe4","last_modified":1507714028770},{"schema":1507714023132,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"RqFXxGPuA18=","id":"c75a0024-f08d-49e1-b8fc-1ca9bbb47965","last_modified":1507714027119},{"schema":1507714023132,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhPSY=","id":"ddb917af-e251-48bc-91eb-59076ddf8494","last_modified":1507714025550},{"schema":1507714023132,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhNLo=","id":"e606e8ce-32ef-4ffe-b9fd-7eced767b9b2","last_modified":1507714024574},{"schema":1507713904138,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407559","who":"","why":"","name":"","created":"2017-10-11T10:26:59Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABQaHhOT4=","id":"259ff0a7-151c-4b7e-b449-98922b6bbfe3","last_modified":1507714023126},{"schema":1507713895934,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy","serialNumber":"AeNmeF8oVpDp/4GPvA==","id":"82e8996b-8424-4e5d-849a-9cb6c134773b","last_modified":1507713902396},{"schema":1507713895934,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJERTEQMA4GA1UECgwHU2llbWVuczERMA8GA1UEBRMIWlpaWlpaVjAxOjA4BgNVBAsMMUNvcHlyaWdodCAoQykgU2llbWVucyBBRyAyMDExIEFsbCBSaWdodHMgUmVzZXJ2ZWQxITAfBgNVBAMMGFNpZW1lbnMgSW50ZXJuZXQgQ0EgVjEuMA==","serialNumber":"WW8OCQ==","id":"a8ba8579-79d8-494e-b5bc-f9b8a6efae71","last_modified":1507713900874},{"schema":1507713895934,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MIGRMQswCQYDVQQGEwJERTEQMA4GA1UECgwHU2llbWVuczERMA8GA1UEBRMIWlpaWlpaVjAxOjA4BgNVBAsMMUNvcHlyaWdodCAoQykgU2llbWVucyBBRyAyMDExIEFsbCBSaWdodHMgUmVzZXJ2ZWQxITAfBgNVBAMMGFNpZW1lbnMgSW50ZXJuZXQgQ0EgVjEuMA==","serialNumber":"AaoZYg==","id":"316627fa-3b68-48e4-909f-9fc58fc69a62","last_modified":1507713899233},{"schema":1507713895934,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydCwg==","id":"7696b73a-52f8-4902-b6b5-130d22222f15","last_modified":1507713897487},{"schema":1507664495795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1407558","who":"","why":"","name":"","created":"2017-10-11T10:24:52Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BEeJFwO0nu759EPo9tKluw==","id":"113485f8-45db-488e-b45a-7917fcf4878c","last_modified":1507713895927},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402158","who":"mgoodwin@mozilla.com","why":".","name":"Certinomis Cross-Signed StartCom certs","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"Wu0lOm5kylP5uOu6md4xmWC3AtQ=","id":"9945629e-f285-47fd-9241-05cb75c041e6","last_modified":1506372739199},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402158","who":"mgoodwin@mozilla.com","why":".","name":"Certinomis Cross-Signed StartCom certs","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"Z7mwlz4NA2s+8dnwRzT/RvK9ZZQ=","id":"0f1e6e75-0f69-407f-bccd-5838401393eb","last_modified":1506372738063},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402128","who":"mgoodwin@mozilla.com","why":"These issue only client certificates and do not need to be trusted for SSL/TLS server authentication","name":"Add Cart\u00e3o de Cidad\u00e3o to OneCRL","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"a0zzyZD4OEdRpzTBCGWFnQ==","id":"b931ec9c-45a9-4719-b2fe-fd6c903b63f1","last_modified":1506372736800},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1402128","who":"mgoodwin@mozilla.com","why":"These issue only client certificates and do not need to be trusted for SSL/TLS server authentication","name":"Add Cart\u00e3o de Cidad\u00e3o to OneCRL","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"ObszBuNYqt9If26rE5MLnA==","id":"1aadc1b7-2a94-4178-9ccb-64ba471135b7","last_modified":1506372735297},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"CcaPWuZtcdneSnerYJH33A==","id":"2f081df6-2a06-4a11-ba8a-368275363e9c","last_modified":1506372734155},{"schema":1506372732033,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"DL0FAAzqeadFvWvsl9xaiA==","id":"07eff59c-72ff-4fa5-bdf6-756974fea58c","last_modified":1506372733055},{"schema":1506282096960,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1400600","who":"mgoodwin@mozilla.com","why":"Three cross certificates issued by the Baltimore Cybertrust Root to the Siemens Internet CA V1.0 have not yet been revoked but should be added to OneCRL.","name":"Baltimore Cybertrust Cross Certificates issued to Siemens Internet CA V1.0","created":"2017-09-22T18:05:01Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydWSw==","id":"f5108d78-08e8-4a73-b7e6-5722bc181931","last_modified":1506372732025},{"schema":1504798796770,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1394595","who":"mgoodwin@mozilla.com","why":"Unknown","name":"Add Firmaprofesional subCA Santander Digital Signature to OneCRL","created":"2017-09-07T11:55:05Z"},"enabled":false,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"QwCyx4wTlCQ=","id":"56e5b51e-6b90-4b87-8ca0-4f58d49e648d","last_modified":1504798798154},{"schema":1504710472553,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1393281","who":"mgoodwin@mozilla.com","why":"Unknown","name":"Add FNMT's AC Representaci\u00f3n certificate to OneCRL","created":"2017-09-07T11:55:05Z"},"enabled":false,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"YcLU1PaprndVkma5ja/WIQ==","id":"756c3e21-c95d-4e5d-b5cb-00da9d658a78","last_modified":1504798796757},{"schema":1504710467849,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"UWMOvf4tj/x5cQN2PXVSww==","id":"0b0401dd-4f39-4740-b911-6ab11ab5edb3","last_modified":1504710470915},{"schema":1504710467849,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"AINVG9I4T2jgQgW4N9SNhw==","id":"a1d4104f-7bf3-4c00-9174-29b580030fee","last_modified":1504710469413},{"schema":1504554095483,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1397312","who":"","why":"","name":"","created":"2017-09-06T16:07:44Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BUE=","id":"d081997f-6074-4f9e-b5b8-aa572a1d3177","last_modified":1504710467840},{"schema":1503344581703,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1392378","who":"","why":"","name":"","created":"2017-08-21T20:42:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeLBg==","id":"e130c036-75e7-4e76-a93a-392fb9568b30","last_modified":1503344586238},{"schema":1503344581703,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST EV SSL Sertifikas\u0131 Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"AUMyuCiycPJJ","id":"e8c04b9e-6bbd-4fbf-bcb0-a2177ac9c04a","last_modified":1503344585208},{"schema":1503344581703,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST Nesne \u0130mzalama Sertifikas\u0131 Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"Aay2vr4aoUeZ","id":"af014072-16c1-4375-94ac-e8ee7611ccd3","last_modified":1503344584093},{"schema":1503344581703,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1381863","who":"mgoodwin@mozilla.com","why":"CA request","name":"T\u00dcRKTRUST Basit Elektronik Sertifika Hizmetleri H5 - Add TurkTrust Intermediate Certs to OneCRL per CA's request","created":"2017-08-21T16:42:55Z"},"enabled":false,"issuerName":"MIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1","serialNumber":"AZkNBFXrl1Zg","id":"5b62df54-5b45-424c-b126-a6442013861a","last_modified":1503344582959},{"schema":1503344499200,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1391095","who":".","why":"https://groups.google.com/forum/#!msg/mozilla.dev.security.policy/Qo1ZNwlYKnY/UrAodnoQBwAJ","name":"Add AC FNMT Usuarios certificate to OneCRL","created":"2017-08-17T17:54:25Z"},"enabled":false,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"RV864VwhzbpUT4KqR1Hr2w==","id":"5e3a7625-ad9e-4713-89e7-3cddd3c0a781","last_modified":1503344581693},{"schema":1501513255358,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"ATk=","id":"b2eaf8f3-f13b-4294-9a7c-5f70cda440b0","last_modified":1501513259932},{"schema":1501513255358,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"ANU=","id":"d91f7502-e635-4fa6-b2da-9dcbac7a73b5","last_modified":1501513258828},{"schema":1501513255358,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"QOu0a5Z9rCkw6Nk7Rg1/AQ==","id":"c302fc31-c64b-4105-bec4-2895e7201f97","last_modified":1501513257806},{"schema":1501513255358,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"Xmo3AIW2VHeeJoR0o09RGQ==","id":"5be4587b-7e7d-4362-90ae-ec54e5c84a59","last_modified":1501513256610},{"schema":1501443689673,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1385914","who":"","why":"","name":"","created":"2017-07-31T16:00:52Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"SeEzbpTltqUtqW7UiuJ2","id":"8dd80d48-07b1-419d-9992-dac30fced89e","last_modified":1501513255352},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"RMgdRGEBv0KzFCjgGFp0Hg==","id":"5f913c3e-d525-4ecf-b374-45e1e40d75b1","last_modified":1499778717805},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"E/YGRk12iZqZuMfsIiVaeg==","id":"398c4ee1-de04-429c-8dbb-cdc0c232b145","last_modified":1499778716926},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"O2Qh+qhbBRuZA11yDhcLGQ==","id":"d87aa7c0-507c-4795-b4c5-812e387c3eab","last_modified":1499778716028},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"D/VlGqmz9Nai1ywCydT/RQ==","id":"6094fb26-7fbf-48b0-83b0-42750450cb4e","last_modified":1499778715137},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==","serialNumber":"B8f7CHJUqV3VareLPE+2kA==","id":"33c37dfe-6270-49e8-b437-e593e6905679","last_modified":1499778714260},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"HVRikKXRQ1ouhOpYcOna/A==","id":"18c1851b-db94-4913-8688-368d7ed7bc61","last_modified":1499778713388},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA3IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNA==","serialNumber":"RmI44ARDVCUOgXNK9ACAbg==","id":"f4213dc2-9eb3-44a8-8be4-accb6d408075","last_modified":1499778712492},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"Aj/CJN2QWZAF25GXPXADOA==","id":"03a9b3e7-7787-41db-98db-e2fbd024ef45","last_modified":1499778711624},{"schema":1499778709795,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQQAAATjkOB1sAAAAAg==","id":"1b74aa7b-2506-48bd-88bc-39af44ee70ce","last_modified":1499778710731},{"schema":1499715699892,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1379974","who":"","why":"","name":"","created":"2017-07-11T14:11:47Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=","serialNumber":"JGKKnm00uOQ=","id":"c6c10916-eb0c-4c4f-a812-4d6390e8a738","last_modified":1499778709784},{"schema":1498049027291,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAlVTMQ0wCwYDVQQKEwRWSVNBMS8wLQYDVQQLEyZWaXNhIEludGVybmF0aW9uYWwgU2VydmljZSBBc3NvY2lhdGlvbjEcMBoGA1UEAxMTVmlzYSBlQ29tbWVyY2UgUm9vdA==","serialNumber":"B2VhZAPxCDH3s9Mkbu3HfQ==","id":"4961246c-b140-4db0-87d7-d240f049b67e","last_modified":1498049030788},{"schema":1498049027291,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"ANUANvVYN7xqAISA9rvJPzQ=","id":"bdb19be5-1d67-49a9-bd7e-a7bbd8dcccad","last_modified":1498049029660},{"schema":1498049027291,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1375006","who":"","why":"","name":"","created":"2017-06-21T13:43:45Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQQAAATjtdPY5AAAAAg==","id":"fe6d33ba-fc97-485c-9b8a-639dd6d150d8","last_modified":1498049028433},{"schema":1497542826302,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1374809","who":".","why":"Private key leaked","name":"Leaked private key for Cisco cert","created":"2017-06-21T12:45:09Z"},"enabled":false,"issuerName":"MF4xCzAJBgNVBAYTAlVTMTAwLgYDVQQKEydIeWRyYW50SUQgKEF2YWxhbmNoZSBDbG91ZCBDb3Jwb3JhdGlvbikxHTAbBgNVBAMTFEh5ZHJhbnRJRCBTU0wgSUNBIEcy","serialNumber":"ZhcM4uyLfYi04utzLnOP46Z89nI=","id":"bb8ba6ba-4e19-407d-ab9d-9f8aafd2c312","last_modified":1498049027284},{"schema":1497542606111,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372336","who":".","why":"Banca d' Italia does not have a current audit for Baseline Requirements compliance","name":"Banca d'Italia Root's X-Certificate","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemaA==","id":"7df83512-01f2-4d2c-af53-fcf4d87defd9","last_modified":1497542609610},{"schema":1497542606111,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"RsdOCxepZXHEs1ErwPc=","id":"b21c90ad-5618-40c1-ac75-eaf73b2c333b","last_modified":1497542608552},{"schema":1497542606111,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByembQ==","id":"e7397769-a603-486d-9696-84693b277203","last_modified":1497542607254},{"schema":1497469289620,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1373288","who":".","why":"","name":"Revoked intermediates","created":"2017-06-15T16:43:23Z"},"enabled":false,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byemaw==","id":"148f7a38-535a-4097-a7a5-83abc4e35800","last_modified":1497542606104},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:06Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"MWzraR3LLhU9m/qKEhvVLQ==","id":"47786d55-ed71-461d-8ea0-3b074caac874","last_modified":1497362467654},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:05Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"eViJ2GX26lp5HbF+XNp1kQ==","id":"38355da2-f5ab-4882-a7e8-78ea5fc41e39","last_modified":1497362466761},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:04Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"U3KGm6UTqJ/nsMyteiUa2g==","id":"071f5229-616f-4ad1-a506-b48a9dbce21c","last_modified":1497362465694},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:03Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"OgxXyntHYBXnPAHDxY0OXg==","id":"95b7cd91-57b5-4e72-aa52-6a0546883af5","last_modified":1497362464680},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:02Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"GTPOETOFf5mIsbuzrojGfw==","id":"a7e4d7b5-50b7-412f-8592-ceb4f6db29a8","last_modified":1497362463643},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:01Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"NpsJHyt3o1U47AAgw3UNXA==","id":"f2e9d2ab-7220-460e-b4a4-02f3675e7a66","last_modified":1497362462415},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:01:00Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"RbG+tfPUe/vBRfTZF54i8g==","id":"9d320894-4ac4-49fb-bfcb-a71d97ebfe01","last_modified":1497362461438},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:59Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=","serialNumber":"dhjnNtYx6cojdAE55TgIBA==","id":"fd51db5c-9e30-4cdb-9736-1f10b80376a9","last_modified":1497362460372},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:58Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"Cf0103tCm9oulH1QK0weTA==","id":"a02fbc88-df3e-4d81-b9e3-7a7088e193b0","last_modified":1497362459446},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:57Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"GuJ0aGBYhChXAOljooJZ3A==","id":"375b3822-bf9f-4c3d-8633-02f7a03597ac","last_modified":1497362458420},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:56Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"OOkLFZaa4CXGyJlLTIEjUQ==","id":"815b19c3-6c68-49fd-b9c4-f488317c9e8e","last_modified":1497362457510},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:55Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"A/kVDQpE7c9h+WxlWQFzSQ==","id":"ae9bb73c-5360-4685-a5e9-8098b95617d5","last_modified":1497362456459},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:54Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"VP3bQF/UdNfxq/UOypU1zQ==","id":"9e057902-89e3-49eb-9e56-f878c1c05f4f","last_modified":1497362455630},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:53Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"G8sz+bm+vQjTpQNBh5CfMg==","id":"d7283b5c-18aa-4cda-9158-fae5ae41ad09","last_modified":1497362454734},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:52Z"},"enabled":true,"issuerName":"MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB","serialNumber":"PmDn14AwWY28IlJeBXkDvA==","id":"43838f76-1ecd-4a7e-9a81-f9f2449f31f1","last_modified":1497362453713},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:51Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"aBXsv0oU3xqh2xkUPOi8","id":"380057fa-8d61-4ee2-a6a1-f6bc5d210e40","last_modified":1497362452684},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:50Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=","serialNumber":"AIZ6Wq/4deFQzwC6NnFpUA==","id":"15c3777b-b91b-461c-99c5-761d6185b109","last_modified":1497362451663},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:49Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==","serialNumber":"APiyCXmwAUq+95DYa3DmGw==","id":"583ee36f-2136-418c-bab7-2d5ed62aad0a","last_modified":1497362450536},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:48Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9vdCBFViBDQSAy","serialNumber":"AL691kTvkemG9UQNa6McQg8=","id":"a2fad4bd-2ce5-4ecf-97e2-1612bde41ed2","last_modified":1497362449522},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:47Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"AI7cApIcPA3cfSpQMf40onQ=","id":"7b9f5e88-b3a1-4071-ad7f-fce8459aa3a5","last_modified":1497362448476},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:46Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"OUOBG6TE0Lr+uYYGxeVbHg==","id":"418575d9-15aa-4b24-9ba5-3764748e3245","last_modified":1497362447464},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:45Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9vdCBFViBDQSAy","serialNumber":"QFLH3Zrq+I5WQ6TlWzfUxA==","id":"65123c45-adf1-40a7-9531-a66d818ae6ab","last_modified":1497362446438},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:44Z"},"enabled":true,"issuerName":"MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"fqRDfSf8haCEh2nWE6O+bA==","id":"07e6dcee-ed47-4aa9-bc69-cd8c50be9eaf","last_modified":1497362445416},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:43Z"},"enabled":true,"issuerName":"MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"eohOGeS5ZHJeptyBvCu/mQ==","id":"11009f24-3e40-4372-82cb-c640be931a51","last_modified":1497362444493},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:42Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnY=","id":"d4cc9f44-f6a3-416d-92f5-d9d1242eff77","last_modified":1497362443469},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:41Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm0=","id":"d448448b-1f23-4815-a563-c4a7996615ce","last_modified":1497362442343},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:40Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnQ=","id":"04f35e34-8280-4b48-a5b3-bb61b27445be","last_modified":1497362441423},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:39Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnE=","id":"133ff174-70c2-4cdf-b8d4-4bcc3db4b004","last_modified":1497362440295},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:38Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"LYTXWk7gMu8=","id":"3b0df03c-394f-43bf-bafd-6da07eca3c10","last_modified":1497362439285},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:37Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"azAcTWL+ijs=","id":"0e15f9c5-75e7-4b8c-9f10-99f8998eda98","last_modified":1497362438146},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:36Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE6YA==","id":"73604eec-92dd-48a5-a040-b5644c4c9799","last_modified":1497362437119},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:35Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE6Xw==","id":"7e3d897e-9724-443f-842b-2124ee1cd062","last_modified":1497362436009},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:34Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"ATE5Ig==","id":"cfe99f95-d3d1-4d4e-b312-6a7a0efedf09","last_modified":1497362434869},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:32Z"},"enabled":true,"issuerName":"MGkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOjA4BgNVBAMMMVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBQZXJzb29uIENBIC0gRzM=","serialNumber":"f43O9TualR8=","id":"ab95e89b-21cc-49c0-b4ac-0d1a3773b334","last_modified":1497362433845},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:31Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABL07hW2M=","id":"a2b93b68-1670-4c9d-a94d-e792364d24d4","last_modified":1497362432728},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:30Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABL07hXdQ=","id":"9aba77c3-ae07-443c-a0ba-ca01aadcc3eb","last_modified":1497362431692},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:29Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hRxA=","id":"9065a612-801b-4b7b-9e2b-b87d584332a0","last_modified":1497362430669},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:28Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABL07hSVI=","id":"b1bb540b-be1b-4011-81df-998edb912fe1","last_modified":1497362429542},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:27Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/UQ==","id":"891cdd11-90ff-435c-9688-1a9e7aeb3a70","last_modified":1497362428621},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:26Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Tw==","id":"43770c43-8568-4d25-b5f2-52623d4fcf78","last_modified":1497362427700},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:25Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeBQg==","id":"9ea34ca2-9f9d-483e-8a49-c3a17d055d47","last_modified":1497362426780},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:25Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Tg==","id":"3d2ac953-a4f2-4f59-a7a6-7c9a8fadf2ca","last_modified":1497362425753},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:23Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/UA==","id":"78529990-77c3-404e-93bf-308ebf7033e9","last_modified":1497362424834},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:22Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd/Ug==","id":"91e8f996-738a-4ff5-bf6a-4823c963d8e5","last_modified":1497362423604},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:21Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfJhw==","id":"7e2f71f1-6463-460c-b6ce-2a8b25624d3a","last_modified":1497362422585},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:20Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeekA==","id":"9a55265f-72e6-4e38-b23b-b3f097136daf","last_modified":1497362421456},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:19Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bycfmw==","id":"d29166c7-29e9-4b00-878f-99f6a415a4d2","last_modified":1497362420326},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:18Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycfpA==","id":"b02d1c65-499b-4cf9-a2e5-cd3d172c06f6","last_modified":1497362419199},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:17Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BycpYA==","id":"b544067a-575f-417a-ab9f-a9ef880c262e","last_modified":1497362418087},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:16Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydIoA==","id":"f91cf838-8125-41b5-9f6f-46891375de0d","last_modified":1497362416981},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:15Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"GA==","id":"a980e313-d1dc-41dd-9bb8-921862a834be","last_modified":1497362415923},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:14Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"Eg==","id":"8e1465de-a917-4608-b44b-ef02800eeb0a","last_modified":1497362414917},{"schema":1496420793982,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1372586","who":"","why":"","name":"","created":"2017-06-13T15:00:00Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=","serialNumber":"HQ==","id":"d61c0990-8c57-4141-9fe4-d5a0f46371ec","last_modified":1497362413918},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"Rea7UUYH3jl33BryPIo=","id":"3f5a142c-40a3-4c89-9df1-a056702b984e","last_modified":1494458678750},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"RvCM2iRdkCE82ZOO2dU=","id":"3e1798dd-0356-44c2-917f-76b2f32ee998","last_modified":1494458667510},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=","serialNumber":"RdHgEmEIjdyRFWDRRlk=","id":"f8ebfd47-13fb-46c7-9b4d-334526c6ded9","last_modified":1494458658573},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R/j2qA==","id":"2ba77577-428a-4f7d-9d54-b088ecb696b2","last_modified":1494458649435},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jvb3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QAEy3RIAAAAAAAAMweH5dw==","id":"81126721-940c-454b-bd0e-f538cd5ab646","last_modified":1494458639464},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jvb3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"DL8=","id":"ff5d47b7-cb50-46f9-9da8-e778892a2caf","last_modified":1494458631103},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"AMs=","id":"6ff3473b-bd64-4b79-98c4-4622661c8e80","last_modified":1494458620210},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"AZ0=","id":"6aa5cbdb-19fb-4f57-9a4e-ddfbf06f50ae","last_modified":1494458595987},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=","serialNumber":"cx0HrIEQg8JHWTP7DzOxSQ==","id":"bcd2cb94-3cd2-49df-a372-50a258804cc1","last_modified":1494458581014},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"A4g=","id":"124dd7d2-59e3-4eb1-b93a-5e9a33cd6e4f","last_modified":1494458571110},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==","serialNumber":"A4w=","id":"0b21265d-dcfb-49c0-b9e9-e900412c1fdf","last_modified":1494458562276},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"APt5i5rs4dIIQPwZdk9/ISc=","id":"058e5554-d206-4b11-9791-dff120803f83","last_modified":1494458553816},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"OGPFrg==","id":"f27c1519-908d-4dca-a797-024c43844b52","last_modified":1494458545573},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByemaQ==","id":"cbc37076-9136-40fa-a079-4d443b7071ca","last_modified":1494458533053},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byemag==","id":"b9762946-8b71-40cb-844b-cafa2c0aed12","last_modified":1494458523822},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfDtA==","id":"4b8b97f0-8a72-4ff1-af47-2fcd773c900f","last_modified":1494458510233},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydvrw==","id":"c3724a4d-2ed5-46a0-87dd-d7d339549c8f","last_modified":1494458498850},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQKEwVUYWlDQTESMBAGA1UECxMJUG9saWN5IENBMSQwIgYDVQQDExtUYWlDQSBJbmZvcm1hdGlvbiBQb2xpY3kgQ0E=","serialNumber":"UbQGvw==","id":"20dc1a34-8afa-4d47-856f-810cc0a6f229","last_modified":1494458484988},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"LAVIFm0MWZYH+Sv8Vf+IqkM=","id":"d8f28ce2-8ee3-41a1-9bc0-ddad36f7c72e","last_modified":1494458469413},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"QM1zZ4GZ4gfwpQtUYye3Ne0=","id":"e35ececb-f12b-4fe4-bef8-ff7c3099fbe8","last_modified":1494458454435},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"YUlF+VXF2FWFqCo472HfZlw=","id":"0e806ef9-c9d4-455a-a462-cbb897cd8e20","last_modified":1494458439140},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"IHj3eiEK3K1Xrpu1uvtBuvE=","id":"023bf60f-9ed8-41ef-8ccb-1bf993f3f973","last_modified":1494458422758},{"schema":1494458377062,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"RVWTeb5EKqE7cy7MUD2oJ3M=","id":"e5723e05-8b15-4cdb-b996-4d36b419a431","last_modified":1494458398872},{"schema":1494453885285,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1343305","who":".","why":".","name":"Revoked intermediates","created":"2017-05-10T22:53:40Z"},"enabled":true,"issuerName":"MIG+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQDEylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMg==","serialNumber":"UdNjvA==","id":"917e8337-dd57-4b8a-8994-2921f2fb69ef","last_modified":1494458377056},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA5iEg==","id":"16319df7-453c-d980-4624-d73d9cf43143","last_modified":1485907697001},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:37Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydSYg==","id":"ec171905-2990-30e0-74bb-9fc327c1c4bd","last_modified":1485907696954},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"Iqpyf/YoGgvHc8HiDAxAI8o=","id":"6fa017d2-461c-8de0-f8a1-ab0531097d8e","last_modified":1485907696908},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"Hwexgn/ZCJicZPcsIyI8zxQ=","id":"4df86909-6b1c-f7cd-c71b-bb4b895d441f","last_modified":1485907696863},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"RnQ3dg5KdDZs0nyFZk4=","id":"0971a89d-b11f-97c9-2ac2-f706757b75fb","last_modified":1485907696819},{"schema":1485795317518,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1334069","who":".","why":".","name":"Revoked intermediates","created":"2017-01-31T23:06:38Z"},"enabled":true,"issuerName":"MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==","serialNumber":"RnQ3dYovwvB0D5q2YGY=","id":"d739cdcd-0078-92a9-2c46-6a5231f3d888","last_modified":1485907696773},{"schema":1484704580928,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"ALxyZmb/WL/wAuUiPK5oK/g=","id":"d6bedca3-c2b7-0402-337e-7788b9c97b85","last_modified":1484704581273},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkGA1UEAxMiQ09NT0RPIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"AKrMYlJmUUin8FOM/0TJrmk=","id":"42e2ce60-f40f-97a6-dd47-3ea2e2dd72d8","last_modified":1484704580920},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQQ==","serialNumber":"e7wSpVxmgAS5/ioLi2iBIA==","id":"59b02ba9-97ec-924b-d797-2c61c2be0d87","last_modified":1484704580894},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydrxg==","id":"224d1360-5aed-b81f-f24c-3d34e2ca3ec4","last_modified":1484704580868},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc85g==","id":"25a0eefb-aa44-23df-4dda-bb166836d4c1","last_modified":1484704580840},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"CdYL9vSQCEKzBwjO10ud2w==","id":"479ac2a4-7b6a-8db3-c5a2-be10eb5dec57","last_modified":1484704580815},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"fbsHfUkagQtznc3rtY1uDg==","id":"b1b1a5db-3c68-21be-8264-7146b0ee9e6b","last_modified":1484704580787},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"AJiU+bpWh2Uc4xFRf8GM9yA=","id":"60daf8a1-a929-0177-e7ba-76fff95fd20b","last_modified":1484704580760},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"Hnms0W0OxHSYE2F0XE97sw==","id":"55b72394-f4c1-3001-cf84-10f2068f2768","last_modified":1484704580734},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bye2Cg==","id":"e2277fc3-1aac-7c20-0cb7-f4fd6c79eedb","last_modified":1484704580708},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"CMNfzETd7XxesS9FOUj9Mg==","id":"49251465-af0d-3e93-cb1a-9d0b2ac356b2","last_modified":1484704580680},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUw=","serialNumber":"XJ8pGvGNM9RIcLUG9YQjLQ==","id":"c83b4498-ea23-7723-1c2c-b673115792d8","last_modified":1484704580653},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MGoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xOzA5BgNVBAMMMlN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBTZXJ2aWNlcyBDQSAtIEcz","serialNumber":"e9JTGBe45yw=","id":"20d69a85-62b2-72c7-1107-110b43d2aeb2","last_modified":1484704580623},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpGcmF1bmhvZmVyMSEwHwYDVQQLExhGcmF1bmhvZmVyIENvcnBvcmF0ZSBQS0kxIDAeBgNVBAMTF0ZyYXVuaG9mZXIgUm9vdCBDQSAyMDA3","serialNumber":"YR0zGQAAAAAAAw==","id":"4204c7d6-1838-5925-2461-1bc0e03515d4","last_modified":1484704580597},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AQw=","id":"f8c41076-a3f0-439a-9d5e-41e27e019a77","last_modified":1484704580571},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx","serialNumber":"ESDDtMgFFiaUfKo7HD9qImM7","id":"ec0960f7-7ae1-23e7-5006-6652da817daa","last_modified":1484704580544},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"RFlmmjulj6Ve7PfBi44nnw==","id":"0e7b9a2c-3604-5b89-4dff-796122174bdc","last_modified":1484704580517},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx","serialNumber":"ESBrHE7sFC7CQ8EM681xA3CY","id":"0595dc75-9356-ba32-a15e-05e3072b7f54","last_modified":1484704580491},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjpW","id":"b7e26b4d-bbe1-1c4e-ef9b-12471bcb9bf8","last_modified":1484704580465},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"a9rf7/BmG9JkKvRuy7J5QA==","id":"fcfc3b3c-0a59-d143-f5fd-7600dd8efa87","last_modified":1484704580438},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ZECgRdZEsns=","id":"4652f392-127d-a5bf-4ed6-b07b9fa72247","last_modified":1484704580412},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"AJBQSPqrEvDE2Hz8xH39Low=","id":"c279dd67-2ce1-e090-1e04-0c11fe3ddf8e","last_modified":1484704580385},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"frj5jTuqBnQ4fljPvVU3KA==","id":"85acb18c-16b6-12c7-83ae-1e0d94251362","last_modified":1484704580358},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfFnw==","id":"d0da2ea3-1cad-5c9e-4c75-c83acfeabc8d","last_modified":1484704580332},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:58Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByembA==","id":"fcd51190-7eaf-291e-b6e5-45e447de7291","last_modified":1484704580305},{"schema":1483471396473,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1329981","who":".","why":".","name":"Revoked intermediates","created":"2017-01-18T01:12:57Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"RH7WhshwXRK6f0VfOfjXgQ==","id":"003234b2-f425-eae6-9596-040747dab2b9","last_modified":1484704580277},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"SurdtfsuPcXXDpY2LkBpYO6BT7o=","id":"034627e4-44c6-fbf2-275a-4ed3431a4094","last_modified":1483471394790},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Er0moq4zwH8ke2pYafIKdg==","id":"85c81ed8-787f-ffcf-2a63-1be622db8d04","last_modified":1483471394768},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydiAg==","id":"9194c97e-3baa-0446-9642-0d6211c3f019","last_modified":1483471394746},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"eLumDUO40KwnecZLJxFM2A==","id":"c2cc63c7-5274-9901-5f67-0a13355a8aa8","last_modified":1483471394725},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Bw==","id":"92e2494f-f3cd-7638-7fe1-a3cb8d8939fa","last_modified":1483471394702},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"GpO48aJ8GngtwECqZhm/xA==","id":"bdfdc34f-ba9a-7b25-6cb6-24c547eb8a10","last_modified":1483471394681},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSgwJgYDVQQDDB9EaWdpZGVudGl0eSBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"Cw==","id":"7574eb9e-6978-dcb7-5a6f-d4c3dd855254","last_modified":1483471394658},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"IA==","id":"d82f446f-181a-5ac3-0ced-854e3cde100c","last_modified":1483471394635},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"OfJBIhFwAdQ=","id":"b8fdddf1-27c1-5f6e-58a1-295e2c8c0ea5","last_modified":1483471394613},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"MABJTA==","id":"71e08617-c00a-8b62-53c2-2a61e21e6155","last_modified":1483471394591},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"HA==","id":"6a6d36e6-8939-0a83-3fd5-c38652b165ed","last_modified":1483471394569},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:55Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSMwIQYDVQQDDBpEaWdpZGVudGl0eSBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"DA==","id":"460643a1-23f3-1beb-0f14-ecb4b6e26cc9","last_modified":1483471394547},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CLc=","id":"49eb43cf-91d4-66ce-1a86-b8674ff83d4d","last_modified":1483471394524},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==","serialNumber":"QAAnEQ==","id":"bb5c827f-3458-93fe-f80f-2982f0d19d34","last_modified":1483471394501},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjqK","id":"d6f9a6d9-d936-dfaf-d396-8ae96769ef10","last_modified":1483471394478},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfNeA==","id":"02ec8a09-2ae4-cd2a-4fa1-5037fa945391","last_modified":1483471394453},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"JLiDzgpL7oFNgJN+jIjt7w==","id":"5631f49c-a1fb-803e-ecf2-3ba82ca79f2e","last_modified":1483471394090},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"BwImeaRkSZQLYwFREwKo3R1Jn+8=","id":"c2de8edd-fd89-36dd-63d0-d3a1df92274a","last_modified":1483471394067},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"HxT1XSjIpzjMprp9Qu1gYQ==","id":"46d4712b-6db2-ce7e-0efd-675f3be896cf","last_modified":1483471394046},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5sA==","id":"8acc0cad-dee8-7e2e-1799-e1a7b8b989c3","last_modified":1483471394023},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"BA==","id":"b9ac21bb-8c1e-e562-5418-bbf6f6323c45","last_modified":1483471394000},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"KuzHPJLdK5hNgJRo3R47Ag==","id":"91b7f544-9de1-efea-08d4-4ebafc9a3608","last_modified":1483471393978},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"B+U=","id":"86fe91df-ebb8-f20d-2031-2bc815b14a25","last_modified":1483471393956},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byeaqw==","id":"b97a8dce-04d9-7dba-6463-ae95d61524f4","last_modified":1483471393933},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"LU4d0t7PAsZNgJGZcb+o/w==","id":"efdf0a12-4ba1-f84d-a88d-fc384251583c","last_modified":1483471393911},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABIg08FMU=","id":"6c0561bc-fea3-ba35-bbdb-2b2672b67d36","last_modified":1483471393889},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"AjqL","id":"4be7b89c-27a6-e95e-c6f9-bf652d4a0b97","last_modified":1483471393867},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"FQ==","id":"89946691-d008-fd14-bd7a-443206d647c6","last_modified":1483471393845},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydInw==","id":"e1a83fb0-93df-deb8-68cd-17f4997ea58b","last_modified":1483471393823},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"JD1wxDd8IgmiqX7MyPPg1g==","id":"f5ad7ea6-4ac9-b9cd-776f-d2afb53fb91b","last_modified":1483471393801},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SqA==","id":"ad8a2f72-7124-3e33-3060-414ce2bd8be3","last_modified":1483471393779},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEdMBsGA1UEAxMUQ2VydGlub21pcyAtIFJvb3QgQ0E=","serialNumber":"J8mznxvTvOR5p4Br3a3sm5j5iM0=","id":"d3f6b499-297d-e9c8-081c-44e2331bcf29","last_modified":1483471393750},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"AIChpbGNqu4XKp9J70syKEs=","id":"f184ba74-06de-9247-104e-160b6d210962","last_modified":1483471393727},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"Cj0=","id":"c5fdcbc2-71d8-0a58-3375-0c7d92526cf1","last_modified":1483471393705},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Aw==","id":"0e8a05ee-feae-fc46-15b9-eaa2d11f4a60","last_modified":1483471393683},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABRE7wRk4=","id":"ac8d3825-3fef-6d3e-2690-7360d1ef57a4","last_modified":1483471393659},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5sQ==","id":"4b03d4c1-705b-458e-5bdc-f729f67eeb91","last_modified":1483471393637},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGsxCzAJBgNVBAYTAklUMQ4wDAYDVQQHDAVNaWxhbjEjMCEGA1UECgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxJzAlBgNVBAMMHkFjdGFsaXMgQXV0aGVudGljYXRpb24gUm9vdCBDQQ==","serialNumber":"WJ2qHzWUqTk=","id":"f93061a9-8afa-1d74-e063-4134d318f00b","last_modified":1483471393615},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"VUtahOwvvmJFwlvmGDZP5w==","id":"9c88bc12-466d-fcdd-cc53-349d4e041332","last_modified":1483471393592},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"L1fHogsVxmfMBka5q4uzaQ==","id":"d3c14505-c104-150c-0a2d-e5f9e92b6152","last_modified":1483471393569},{"schema":1483471393228,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:55Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"cJ+vg4742XhNgJW2ot9eIg==","id":"58bf9d8a-9a68-b41f-453c-8af8844bc07c","last_modified":1483471393547},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"LizeWXFWP5pZPI/dLc+PVQ==","id":"cb1a1172-56d6-4150-1f50-eb2131f442f5","last_modified":1483471393221},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Ew==","id":"a0ff8e3f-e68d-5ee2-21e3-26cd0f46673b","last_modified":1483471393199},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABElatX7I=","id":"00ac492e-04f7-ee6d-5fd2-bb12b97a4b7f","last_modified":1483471393177},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy","serialNumber":"ANX8SnNRxCmsE/GCl5hw+8A=","id":"a09db9b3-2faa-73ab-67ff-61dcbf700ec7","last_modified":1483471393155},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"VBSf+IncsTB3RZS4KFCJPQ==","id":"7e816865-7c1d-2519-f114-e69a280768f4","last_modified":1483471393133},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MFIxCzAJBgNVBAYTAk5MMRkwFwYDVQQKDBBEaWdpZGVudGl0eSBCLlYuMSgwJgYDVQQDDB9EaWdpZGVudGl0eSBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"DA==","id":"5b760d02-fdd7-d6be-cb6f-4d30bf97746e","last_modified":1483471393111},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QDi5rw==","id":"7de029af-ddf3-02be-ca26-5bb95b080d14","last_modified":1483471393088},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"MABJSw==","id":"411b4e82-2ddd-20c2-20b3-8d77145f6901","last_modified":1483471393066},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermwtg==","id":"9d8a83d8-d651-42a0-ac1c-0ee414f3e31a","last_modified":1483471393043},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey","serialNumber":"Nbc68Q8EHza72P/hSWcddw==","id":"d0513de2-6da9-d68d-78cc-a2292a9d18fb","last_modified":1483471393021},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Ig==","id":"872ba8c8-a236-9ac0-85ea-08630f5b17e2","last_modified":1483471392998},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:52Z"},"enabled":true,"issuerName":"MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"APdCebq8ZyZr/T0luxlicNw=","id":"7a24e461-9fd0-b17f-01e0-f44866b800f1","last_modified":1483471392976},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermw0Q==","id":"fff46511-7357-4559-3d36-75fc74034299","last_modified":1483471392954},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"Ajp/","id":"272f2a95-6aec-f333-22ad-709d6118a87b","last_modified":1483471392932},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Fw==","id":"4f0dfd30-9278-4f20-25c3-436798595b84","last_modified":1483471392911},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=","serialNumber":"K1ftto7Xcb0YKwQ6uMvOIA==","id":"29eab149-524e-b1da-e2b9-dc4a784ab64b","last_modified":1483471392889},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAFQ==","id":"91609507-ef23-7672-3a5d-06dfb9b0dac4","last_modified":1483471392867},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAx","serialNumber":"U+1Y1QpJc0FOR5JdCJ01gQ==","id":"79f39790-1151-6bb2-0a50-fc596b82bedd","last_modified":1483471392845},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TAA2G+UIK6mqznQKBT77NA==","id":"d51879d6-0a85-8311-5b14-ad993cec17e6","last_modified":1483471392823},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Iw==","id":"532dd854-cdef-6452-2793-1e36d091d9ec","last_modified":1483471392801},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/O5w==","id":"756ab100-8a14-daf7-bf06-9fe423863208","last_modified":1483471392779},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=","serialNumber":"Ajp+","id":"41f2401b-5c31-724f-ad6c-28f3f6f47634","last_modified":1483471392757},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MFExCzAJBgNVBAYTAkpQMRMwEQYDVQQKEwpGdWppIFhlcm94MS0wKwYDVQQDEyRGdWppIFhlcm94IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IDI=","serialNumber":"AUa47POQ1dN5","id":"0956d064-8750-eee2-b0c7-7e1c2d1d6f25","last_modified":1483471392735},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:54Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"Pgyeh2mqlVzqI9hFntRbUQ==","id":"134969c5-0bf4-4054-eaa1-b24feaa76aef","last_modified":1483471392712},{"schema":1480617578654,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1315199","who":".","why":".","name":"Revoked intermediates","created":"2017-01-03T18:41:53Z"},"enabled":true,"issuerName":"MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h","serialNumber":"Gg==","id":"141d8e99-193b-d108-382b-7d97e6912d8c","last_modified":1483471392689},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDYXNBhF+dePFjojs7u2vj1","id":"f7f193ca-c34e-866a-8abf-d44188a78cb0","last_modified":1480349168043},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA6BjA==","id":"2a9d41c8-d3e7-a40a-a79a-899902aa73cb","last_modified":1480349168021},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"XhcFm2g619rt8Sro+a4rHA==","id":"a01f2d94-e1ee-2139-5652-c216331e357a","last_modified":1480349167999},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F6QlB/yX+A==","id":"a7fa8b99-3e2a-2c03-dffd-ab341eae59af","last_modified":1480349167976},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydxog==","id":"35f6f9f8-eb17-39d2-50a7-2b40f01e2584","last_modified":1480349167954},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CqnbFQ==","id":"3b60bc42-674b-7822-113f-c8dc6d1b015e","last_modified":1480349167931},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJzdC1IYXJkd2FyZQ==","serialNumber":"Xrr31RF0DoIzMKXS6XtD+g==","id":"c0d2651b-f567-0f6d-ce3c-16e7d19390d0","last_modified":1480349167904},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/SnQ==","id":"7326aa15-9b3e-44ca-c1c5-0ed1ff29521f","last_modified":1480349167882},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzQ=","serialNumber":"H08=","id":"2ac02b19-f616-0dc3-6d01-28e1bea3dd93","last_modified":1480349167861},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:22:27Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"NMpMcEnex3eXx4ohk9glcQ==","id":"8e453b5c-3f81-2694-2f10-73ec8c406c49","last_modified":1480349167827},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAA=","id":"a3b400ad-0b4d-aa11-e8b5-82019fbc84d5","last_modified":1480349167797},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIGpMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykgMjAwNiB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UEAxMWdGhhd3RlIFByaW1hcnkgUm9vdCBDQQ==","serialNumber":"Ikdj3zYXXGsC/Afm9Tvx+g==","id":"e8b2d24e-5aaf-86dd-441e-b4781d5370db","last_modified":1480349167774},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgQ2xhc3MgMyBFViBTU0wgQ0EgLSBHMw==","serialNumber":"acI1CFIgmwSFBoU5+ahDgg==","id":"938358e4-4c70-beb4-0fbe-02009feee6b6","last_modified":1480349167744},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:37Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABA/A35EU=","id":"97fbf7c4-3ef2-f54f-0029-1ba6540c63ea","last_modified":1480349167722},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgQ2xhc3MgMyBFViBTU0wgQ0EgLSBHMg==","serialNumber":"UVKsEezpGWOVQ4W9esstng==","id":"c4c22010-0cb9-e9af-005d-2483612d864e","last_modified":1480349167701},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg/C8eXg==","id":"4295bb93-6e34-a58a-4d1c-238615b57cb0","last_modified":1480349167343},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"AImQERVYPoeb","id":"4ca8f1a1-0dc0-881f-b497-cc5574f2494d","last_modified":1480349167322},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"J2La+q+JOURNWkX60OP2lQ==","id":"8662e9a7-fe16-d1fc-0993-d16dd2f01012","last_modified":1480349167291},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDEgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAxIENB","serialNumber":"BAAAAAABHkSl5ao=","id":"7cfc5a53-f950-c15b-4dbb-8124fadcf871","last_modified":1480349167269},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"RUT1Gehd1KKYPfqOlgspoQ==","id":"8855fafd-e48b-680d-ff15-a022057d9b9e","last_modified":1480349167246},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:26Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABKUXDqxw=","id":"0a92faa8-b870-3a38-036e-9b95185fcb6a","last_modified":1480349167224},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"CqZgEvHAsnzkT//QV9KjXw==","id":"39008976-298e-f664-50c0-56f8ae6c4df5","last_modified":1480349167202},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR8wHQYDVQQDExZHZW9UcnVzdCBTSEEyNTYgU1NMIENB","serialNumber":"OUvvVscW0/NltofkmV9qmg==","id":"a5eb3877-5e7d-200a-cee3-f63b8004d58e","last_modified":1480349167179},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"ORFgmCj072NjcJnrxOMfQA==","id":"995df7f2-6bd4-12c6-b1aa-fcfe7618b193","last_modified":1480349167156},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltms=","id":"460ae779-c915-9daf-9a13-e0bf953322cb","last_modified":1480349167125},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155119","who":".","why":".","name":"T-Systems intermediate certificate","created":"2015-05-05T11:10:09Z"},"enabled":true,"issuerName":"MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==","serialNumber":"ARQ=","id":"2826cef9-e4b4-53f9-e3cf-c5870fc778dd","last_modified":1480349167102},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:49Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"DAk9hy8DhHSo+aQetvPB/fY=","id":"b42066e0-0c88-e02b-620f-c41c2118c4e7","last_modified":1480349167079},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1309305","who":".","why":".","name":"Hongkong Post e-Cert CA 1-10 certificates","created":"2016-11-03T12:48:38Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BHk=","id":"5048a7c5-79c8-68d7-06a3-19e8ba32e5fc","last_modified":1480349167057},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"OnvXX72mvUI2Id/NMzegmg==","id":"92d843e8-4e72-2832-b56f-6e488e677d0f","last_modified":1480349167035},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEiMCAGA1UEAxMZR2VvVHJ1c3QgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"ZgwfEqZnBsUNvNuZ77FbQA==","id":"73ae5fed-730d-94db-04ef-2aafd5ff75b8","last_modified":1480349167012},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Qh/QbQ==","id":"6e4739fe-1aed-2320-4dc3-832043a31fc8","last_modified":1480349166989},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"L79XLVO2ZmtAu7FAG8Wmzw==","id":"7d2a48b3-0b2e-59ae-2002-8edb4da20bd2","last_modified":1480349166968},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"BUrYjru5px1ym4QUN33TOQ==","id":"e95bb238-6d35-2cce-9744-d6a672b0a874","last_modified":1480349166946},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESByNJZ5TPjg9iZyL6a/h5Zx","id":"51935a37-2964-18cf-b34c-a20c2c2250ea","last_modified":1480349166921},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1314673","who":".","why":".","name":"SecureSign Public CA11 intermediate CA cert","created":"2016-11-03T12:46:07Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RDQTEx","serialNumber":"Aw==","id":"ec4f91dd-7560-920a-f178-e8ae460dd595","last_modified":1480349166898},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABFUtaxac=","id":"8d87b3cd-b954-f4f1-bfb2-a0e60645301c","last_modified":1480349166876},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xLTArBgNVBAMMJFN0YWF0IGRlciBOZWRlcmxhbmRlbiBCdXJnZXIgQ0EgLSBHMg==","serialNumber":"ATE3ew==","id":"83ac91ce-0f5e-ae4e-2010-b0da5616cd59","last_modified":1480349166855},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"LnfcUaXG/pxV2CpXM5+YSg==","id":"4c743a6f-af95-49a6-bd4a-d1ee8160c537","last_modified":1480349166833},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1309305","who":".","why":".","name":"Hongkong Post e-Cert CA 1-10 certificates","created":"2016-11-03T12:49:39Z"},"enabled":true,"issuerName":"MEcxCzAJBgNVBAYTAkhLMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMQ==","serialNumber":"BGU=","id":"4de7908c-45e7-3b7f-a91a-8cefb1ecf830","last_modified":1480349166811},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:46Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJZbEU4I=","id":"19c9a896-fbf0-8ad0-92cd-4aca2577c006","last_modified":1480349166787},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABIg08D3U=","id":"4aec7420-aa59-53b8-1373-d3c0a7ebc837","last_modified":1480349166478},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=","serialNumber":"CgFBQgAAAUFcf/EVAAAAAg==","id":"d60a94e9-3f7f-a20f-1dcc-c87ccc78fb99","last_modified":1480349166455},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"dItWlz2V62Philqj9m6Pbg==","id":"abb0df0d-6716-9a25-ae33-806e93276cd4","last_modified":1480349166433},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcL+EA==","id":"3cef2b9e-ddcd-cc40-8d59-49408409a3bb","last_modified":1480349166405},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1263733","who":".","why":".","name":"Disney CA intermediate CA certificate","created":"2016-04-12T12:50:50Z"},"enabled":true,"issuerName":"MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp","serialNumber":"TA6EVg==","id":"7b09e4fc-2261-e7c6-e926-5a7b5e74fc5e","last_modified":1480349166381},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"GdXz4L1b6FKNCMG9Jz2tjA==","id":"35f81fe8-9fa4-760b-9fd0-2de1b0191721","last_modified":1480349166358},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:23:14Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"COwoDFvz7GD8R2K7Lo0rYQ==","id":"cc56260c-5f3a-3f4b-c712-78a8e7facd27","last_modified":1480349166330},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEmMCQGA1UECxMdQ29weXJpZ2h0IChjKSAyMDA1IFdJU2VLZXkgU0ExFjAUBgNVBAsTDUludGVybmF0aW9uYWwxKTAnBgNVBAMTIFdJU2VLZXkgQ2VydGlmeUlEIEFkdmFuY2VkIEcxIENB","serialNumber":"WD1AyQAAAAAAJQ==","id":"8c984ecd-c61c-426a-97aa-3a808e4da482","last_modified":1480349166308},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnI=","id":"333f6eb2-cefe-1a3b-3726-a8320b047847","last_modified":1480349166286},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJQcQRNU=","id":"2258e9bc-1c39-9db3-4fdb-c7eb12d0609c","last_modified":1480349166264},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:15:54Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"Bg==","id":"b7fb6842-6407-8ae4-5e0f-e6daf112ed4f","last_modified":1480349166240},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"IIxFSyNM6mWtCgTG0IL3Og==","id":"6457eeb8-d83a-3818-c416-0dce6d71d471","last_modified":1480349166215},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABHkSl5AQ=","id":"de8e6484-fc97-6889-a1f9-dafd45786606","last_modified":1480349166191},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByeQ9g==","id":"bb5a82a6-8da0-5390-a7d6-843bdb0c02c2","last_modified":1480349166170},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:17:01Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"EQ==","id":"dcce309f-aa60-6484-eaed-aa8310440a5c","last_modified":1480349166148},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"R4af5A==","id":"e60eeeb2-612e-ef08-d0b8-5e9f8e1a23a9","last_modified":1480349166126},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:51Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAAA+X/GIyk=","id":"528cd047-ef3b-fc23-e37f-5d67fd3117e4","last_modified":1480349166102},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"BYyEX2b5+K+myAIR7eXaRQ==","id":"9be08dd3-1922-fb30-77dc-5cfcf00164a0","last_modified":1480349166080},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"RurwlgVMxeP6Zepun0LGZA==","id":"22a74468-602c-f4ac-0003-be4ce0167258","last_modified":1480349166058},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBSb290IENB","serialNumber":"AJiWmg==","id":"1525b265-22d6-3253-079c-c4ffca58458f","last_modified":1480349166036},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCLRVuhcUZaluIgIVlRJx+O","id":"a6299e39-84a4-2dce-ffbb-751107660f4f","last_modified":1480349166012},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:20Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABCUVQ9No=","id":"a1d34c2f-4a03-0e35-ba5f-bc14138bcff5","last_modified":1480349165990},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:26Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABF2Tb8Bc=","id":"7e19f742-420e-dbe9-f691-2d19430d75b2","last_modified":1480349165968},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9Ltm4=","id":"20732fc6-dd20-fe76-b6b5-b78388b64bdd","last_modified":1480349165947},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"fMTRbGCp280pnyE/u53zbA==","id":"44aa21e7-a92c-a0cc-6f6c-85b7ee52a87d","last_modified":1480349165925},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"d8AtKymQwkOPDBj+hjPzFg==","id":"014a5b67-d566-0767-c9d7-48e54115a69a","last_modified":1480349165591},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"Os2rnHWYhryvdOXfgan06A==","id":"dc94f688-044b-f8a0-79f9-5dc2d42e3edb","last_modified":1480349165569},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:19Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"e/fIfg2Dj2tkYIWVu2r82Cc=","id":"9e8ec7bc-0f79-42c2-c9bc-32bfbbd3b591","last_modified":1480349165547},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:16:27Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"EA==","id":"362a0532-ea75-9bc6-2e50-35d9566a6ad2","last_modified":1480349165523},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:06Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"UU3AP1SMxmyhBFq7MRFZmf0=","id":"4f2e59ff-cdf1-48ee-1122-961833187e49","last_modified":1480349165501},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESBqoILo90ntDW7OTK43MS2F","id":"0702b706-86e5-6a48-49fa-6c53b99009f3","last_modified":1480349165479},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"GtXUVojhwOTkaQ4bTKblEQ==","id":"9475e2f6-7247-cbe1-5055-8af86f39a149","last_modified":1480349165453},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"KjoVfZ3by6+pL8fssyfM6A==","id":"f4c8162a-d49b-1cbd-adb9-5e6223793aa4","last_modified":1480349165429},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydr0Q==","id":"a85aef34-3bfe-2135-845d-466adadc414b","last_modified":1480349165407},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Xbevr3ut3Z9m1GuXC9SonA==","id":"549710cf-bcaa-843c-df9d-5962bad88a9a","last_modified":1480349165384},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CeagHQ==","id":"d69db231-b7b5-4d79-147b-49198f93fc10","last_modified":1480349165355},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"EAdmaA==","id":"618009ee-0ef1-af4b-8841-349e6f82eacc","last_modified":1480349165329},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:54Z"},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB","serialNumber":"BAAAAAABHkSl7L4=","id":"636c65b9-2d52-8689-023f-7a23a0baec5b","last_modified":1480349165306},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABFqoAZoI=","id":"2b0d58aa-9c96-748f-4fc0-b1f413ca8e20","last_modified":1480349165285},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1250907","who":".","why":".","name":"IdenTrust cross certificate","created":"2016-02-24T20:04:54Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1c3QxIDAeBgNVBAsTF0lkZW5UcnVzdCBQdWJsaWMgU2VjdG9yMRwwGgYDVQQDExNJZGVuVHJ1c3QgQUNFUyBDQSAx","serialNumber":"fwAAAQAAAUrz/HmrAAAAAg==","id":"352c78aa-997c-bdbe-66ba-930d66fde011","last_modified":1480349165264},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CeFU2w==","id":"e8e298f0-efa2-0d08-458f-c085ee9df8f9","last_modified":1480349165242},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1149603","who":".","why":".","name":"MCSHOLDING intermediate certificate","created":"2015-03-31T14:53:16Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAjg==","id":"c9897d2c-c68e-3c02-2f39-678954b0cf3e","last_modified":1480349165209},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:35Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"bAOrKSMsmA0MLJyAJ5BRsUM=","id":"7d44cb3e-28a5-16dd-024c-796312f780bc","last_modified":1480349165175},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5BhE0zbgQ==","id":"29925947-91ab-16a8-a5af-65558cdb27c2","last_modified":1480349165145},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABL07hUBg=","id":"1240480e-2ef8-8ac3-4314-4e8e494741b9","last_modified":1480349165119},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCyHU+xOECnh9Rf2IvgR8zS","id":"3980401b-c0e2-0533-f0fb-0cc04685d248","last_modified":1480349165097},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CdWFNw==","id":"f06ff510-954e-b917-fda1-2c3153788d7d","last_modified":1480349165075},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"TrKEMhb2PKktH8lHg0AV5A==","id":"8b7985ab-ab8b-fcd2-cf88-cf8dad0f7a97","last_modified":1480349165048},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:56Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJQdAjik=","id":"a75f5980-9149-fff9-70d5-b24121c3eaff","last_modified":1480349165026},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9lw==","id":"59b587cb-401b-a5d0-8128-86c3691c4be1","last_modified":1480349165002},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDMgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAzIENB","serialNumber":"BAAAAAABHkSl6mw=","id":"3cc60c06-a870-951e-1d12-4b29ee13989e","last_modified":1480349164725},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"SdegFrLaFTCsoMAW5ED+zA==","id":"9fbfe267-c715-8f7b-d9ad-166aad9f91af","last_modified":1480349164704},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABMxvC9bk=","id":"923a5e98-11f7-cdae-b073-45b525fb2294","last_modified":1480349164681},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Bydp0g==","id":"10e51569-072a-611a-c397-3050fdf22649","last_modified":1480349164658},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCrvQ==","id":"6d791114-68b4-8c3c-ee3c-29ed83eced2e","last_modified":1480349164636},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAI=","id":"bff9c953-6690-f618-cfea-7b936f3691a6","last_modified":1480349164614},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Aw1SPC56593ZCZ9vCNHKwQ==","id":"c395381f-fe34-7b6c-f56a-f20b20bf0d0d","last_modified":1480349164590},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:22Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABAJmPjfQ=","id":"24b096b4-987f-a21a-04d3-aedc9eaafc1e","last_modified":1480349164559},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABK84yjs8=","id":"8078d5ff-c93b-15d1-ebcf-607bdbfc159f","last_modified":1480349164533},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"FJl6tXgNpSk=","id":"7ab0a200-7ecf-576f-bff9-652fb14c3af6","last_modified":1480349164510},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"M0VSOewW3WI=","id":"f3688c95-3934-e80a-e32f-0d5dcb2f0c4c","last_modified":1480349164486},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"VN2yeFexyXjPf34fHGmbhg==","id":"bbcfc451-2fcc-b380-e579-bb6d11fc7d34","last_modified":1480349164463},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==","serialNumber":"STMAeg==","id":"a46be506-1dbc-41a9-2775-95d67708fb5f","last_modified":1480349164433},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1300977","who":".","why":".","name":"revoked.badssl.com certificate","created":"2016-09-09T16:26:08Z"},"enabled":true,"issuerName":"ME0xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQQ==","serialNumber":"Aa8e+91erglSMgsk/mtVaA==","id":"4b778ec2-ef45-c5b2-dc44-b00c87b11741","last_modified":1480349164410},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"TurPPI6eivtNeGYdM0ZWXQ==","id":"8192a2fa-165d-3759-fd20-4b7d8e2a0e84","last_modified":1480349164388},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAMTFHRoYXd0ZSBTSEEyNTYgU1NMIENB","serialNumber":"UKKK5ol/rKBZchAAOnZjaA==","id":"ca0c5f15-2808-8c94-3f77-6a277d6738b2","last_modified":1480349164365},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"UMUwXwT1Z4juyQ/CNTf4mw==","id":"c623e511-79c8-cbe6-6a6e-0d9896f07e71","last_modified":1480349164342},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dD","serialNumber":"Ew1ee9Jq7Q/Dig3ACF4V6Q==","id":"c011d2b4-73bc-27e5-3d3a-ab00be2a4d05","last_modified":1480349164320},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"XLhHIg7vP+tWfRqvuKeAxw==","id":"520c26f8-9a60-5949-0372-c9d93f9e95dd","last_modified":1480349164297},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"E5I2y6sIonl4a+TmlXc7fw==","id":"ee842f50-9d56-8fdf-fa55-8b55b8519b81","last_modified":1480349164275},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=","serialNumber":"Jq6jgeApiT9O4W2Tx/NTRQ==","id":"3b658f17-11f9-7550-d991-3e9a1397402d","last_modified":1480349164253},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDIgQ0ExJjAkBgNVBAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAyIENB","serialNumber":"BAAAAAABHkSl6Co=","id":"6eb0fa3b-c226-f411-0fab-df88962a5769","last_modified":1480349164232},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESD9YhzIEOwiOT7Nwip+E1KI","id":"d6172148-c2ee-a904-db40-079b10436cca","last_modified":1480349164209},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:17:24Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"Eg==","id":"34561e12-916b-083e-6fa6-181b5b89ec80","last_modified":1480349164187},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"NvEJoRYL2yvAZrAjbDIipQ==","id":"b1119d43-b3b8-1f41-6fbb-9cf2f67a521d","last_modified":1480349164164},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCC9oPNcRdPOox+SjWm9dTX","id":"8858e9fc-cc55-54ea-fe45-c4e533c2e410","last_modified":1480349163834},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1145157","who":".","why":".","name":"live.fi certificate","created":"2015-03-31T11:14:46Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB","serialNumber":"D9UltDPl4XVfSSqQOvdiwQ==","id":"0a9323dd-982f-c62d-a9b4-b9d04617fc62","last_modified":1480349163810},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:35Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"OYBKgxEHpW/8XGAGAlvJyMA=","id":"d6dfdc76-52ae-2843-3484-7fbff46f0100","last_modified":1480349163788},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"EM8bDLBnnoYe4LnWpLIhS4esr3I=","id":"be09b295-68d1-9c01-97ee-10df36acd3ea","last_modified":1480349163764},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:41Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJ/ufRdg=","id":"5d64f82e-9ad8-fde1-a8c9-2d94552a8ad4","last_modified":1480349163739},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:51Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHJRKMpA=","id":"f5b2da3a-5176-b4e4-240a-181f39f6756b","last_modified":1480349163715},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:18Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABBHYoIFs=","id":"f59ed73e-f3c5-eef3-4481-3ca8af0b0688","last_modified":1480349163691},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:37:41Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABHhw1vwc=","id":"1b1856c1-f4f5-82ca-ba57-d94739e74576","last_modified":1480349163668},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"TqfXw+FkhxfVgE9GVMgjWQ==","id":"60f6a3be-ad83-a868-d645-7aad77914bc8","last_modified":1480349163645},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:21:56Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"LdbnCbsA9sOgI4mkUpWXPw==","id":"d839b1ed-7d39-5e57-687c-2f4d6f0514e5","last_modified":1480349163622},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=","serialNumber":"ANygrItIJ2rcKlyS3Lue07U=","id":"d55572d9-be60-5967-948a-7dae793ab30f","last_modified":1480349163595},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydeGg==","id":"b7d8b0e0-9747-6a09-ab6b-051c57579fe9","last_modified":1480349163572},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCVop+Q4/OBgtf4WJkr01Gh","id":"7602529c-c2ea-d18b-9b2a-fdb70ca936f9","last_modified":1480349163548},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:42:31Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABGMG0Gmw=","id":"317aeda4-6de7-7b11-76cb-3b0afa9aaf86","last_modified":1480349163514},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:04Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"O2S99lVUxErLSk56GvWRv+E=","id":"27847bcc-dbaf-196f-ed5e-c1c022798717","last_modified":1480349163492},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:16:35Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"By7fBTreouRwX/qrpgSUsg==","id":"322de470-76d3-a45d-740f-342a6a8eb863","last_modified":1480349163470},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"ezdAeCxKH7BFs7vn3byYaw==","id":"fc5bde6b-45b9-c141-7171-0a6f37e7938a","last_modified":1480349163448},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"VLm3Xe60+1YgPpXCGtXLng==","id":"055d66b6-8fbd-93df-f2c4-dcdb41943212","last_modified":1480349163426},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUaGF3dGUsIEluYy4xGzAZBgNVBAMTElRoYXd0ZSBTR0MgQ0EgLSBHMg==","serialNumber":"cDggUYfwJ3A1YcdoeT6s4A==","id":"093f20b4-93b8-a171-cbe7-3e24a543c7e9","last_modified":1480349163403},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"a9/VeyVWrzFD7rM2PEHwQA==","id":"c02a9772-b351-59dc-8633-1293ac9addee","last_modified":1480349163377},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCis569omrbb20yySF39+aE","id":"aaa19866-32ce-e842-6431-6d357fafe8d8","last_modified":1480349163350},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg6C237Q==","id":"57ddfa31-3f08-298a-d7bd-712e3aaea567","last_modified":1480349163327},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"HZyLf+K70FKc+jomm8DiDw==","id":"452f4798-87d4-8df1-b275-177456d2f1c8","last_modified":1480349163302},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CskruA==","id":"e92cad12-4098-0817-e317-3674d4242ba9","last_modified":1480349163280},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=","serialNumber":"a12RvBNhznU=","id":"33154d98-0f20-7e7d-d2d0-3244a7d1f971","last_modified":1480349163257},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CjM=","id":"283b292b-1212-a713-c8be-c976c0222410","last_modified":1480349162955},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"NTgf4iwIfeyJPIomw2dwSXEwtxQ=","id":"542dbfc0-0faa-2398-9670-cd249525fd2c","last_modified":1480349162930},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cd/dug==","id":"3cf54b7b-336d-7c80-4596-d5a7762329d9","last_modified":1480349162902},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=","serialNumber":"M64Z5ufZzDRVTHkJR1uXzw==","id":"5d6d86a0-7e3e-b832-83e5-afc1eb2e294f","last_modified":1480349162880},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABIBnBjWg=","id":"0713fba9-386c-888f-cbe5-5188ff2696a4","last_modified":1480349162857},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"fWK0j/Vi8vNWg3VAGjc02w==","id":"a4428979-4be6-3ba2-f435-aa8e4574ffe0","last_modified":1480349162835},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xGzAZBgNVBAMTEnRoYXd0ZSBTU0wgQ0EgLSBHMg==","serialNumber":"JpUvYJyWjdGmeoH7YcYunw==","id":"929de7d6-0669-5601-0b8f-9a192bf1cb17","last_modified":1480349162803},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"45KI4WIxyXfNrdtdj7C6","id":"7cb25ddb-9f7e-7297-e8b4-c50d019f0cf7","last_modified":1480349162781},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:15:22Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"BQ==","id":"7c28e9e7-b9ce-f4ed-8d5a-e7b9e534fba5","last_modified":1480349162758},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:19Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"F7PAjw2k0dTX5escPnyVOBo=","id":"3c7e3e8e-5c25-8fbf-0006-2c92256e0a4b","last_modified":1480349162734},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"Sx51x7V8pYe8rp7PMP/3qg==","id":"4006917e-3260-59cd-eb3f-f4d1167cf888","last_modified":1480349162710},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"DHmmaw==","id":"0abfb8ad-d1b7-5f0e-cbea-630f2424171d","last_modified":1480349162686},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcHC/g==","id":"cba8acd8-a291-1ad6-9581-ed647dd5d56d","last_modified":1480349162661},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:53:13Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"ATE0vw==","id":"fc71cbb8-4e2a-2835-d5be-4c48cd3650bb","last_modified":1480349162632},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABLF5/HXY=","id":"ca59600c-e90a-e85a-43b8-22bc76bb0e1f","last_modified":1480349162610},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDI=","serialNumber":"BXA=","id":"a44b5bf8-8158-1924-7626-e1ba2d2031f7","last_modified":1480349162580},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:24:01Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"VOcIuNbTqkpOMUyI108FOg==","id":"43e72628-c1a5-2091-2dcd-41bbde768c73","last_modified":1480349162557},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:53:40Z"},"enabled":true,"issuerName":"MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ==","serialNumber":"ATFpsA==","id":"325bb598-839b-f7aa-8a22-08ab8c09e803","last_modified":1480349162533},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:45:50Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"UV9aaDeNRNtQuXjRYk4Skhg=","id":"c11dd0af-83d5-61ec-63af-5b816a3ae557","last_modified":1480349162506},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"bzTw0uq05TUYEGS98bh0Ww==","id":"6b743fc3-1ce6-8dfe-52f1-9f3e6a31f15a","last_modified":1480349162483},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:21:30Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"Gd/pPu+qLnXUdvP9sW73CQ==","id":"2da11236-c2d8-7804-7de3-ffd711406b04","last_modified":1480349162460},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:09Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJ/v3ZwA=","id":"9f6615be-a0b9-519a-1e26-2bd7aaf5953b","last_modified":1480349162438},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:05Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABGMGjftY=","id":"5f1ab732-8d48-0102-fb50-46ce74fc1a90","last_modified":1480349162415},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"Rvm2CEw2IC2Mu/ax0A46QQ==","id":"82f97501-85ba-bb19-f68f-ca7ce68ca7b3","last_modified":1480349162392},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==","serialNumber":"BAAAAAABJpQ0AbA=","id":"520cee2c-e36a-936e-d551-a51ee9c659c8","last_modified":1480349162369},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"ByfHkw==","id":"74d82589-0fde-91da-20cc-22fbd84cd0aa","last_modified":1480349161997},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESC8DawWRiAyEMd38UXbfgPR","id":"6147b64f-da46-ba30-2b9e-30b515e8f6b9","last_modified":1480349161969},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABK84ykc0=","id":"0a42070f-3149-2b91-1bbe-c54de4ed1be8","last_modified":1480349161946},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnM=","id":"dc28966b-d7db-b55f-1606-c5bff610bf99","last_modified":1480349161925},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"FJl6tXgNpSg=","id":"bab58b65-8ef7-f3c2-fc13-88f72a0840f7","last_modified":1480349161902},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDItX4ruWiLnrlz0rk4/bmz","id":"c12d5f3c-b722-948f-b367-857845ed5e8e","last_modified":1480349161872},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"bx/XHJqcwxDOptxJ2lh5vw==","id":"a0da0bd1-8bec-4c82-fb9b-636ddcde057d","last_modified":1480349161850},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:47:39Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"Mq0P6o03FDk0B2bnJ+mYPGo=","id":"54f096a5-3608-9b68-ddca-a200e799ba06","last_modified":1480349161828},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:43:00Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABJ/ufQg8=","id":"61db13cb-74d9-e675-a1e8-db5f78eb3f4e","last_modified":1480349161807},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABM6d3Z0s=","id":"b9c439ef-fcf3-2263-c14e-80727cbef898","last_modified":1480349161785},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xGzAZBgNVBAMTEnRoYXd0ZSBTU0wgQ0EgLSBHMg==","serialNumber":"FNISyWWTGi5Yco6fGh58/A==","id":"bab0ff94-c98e-7843-97b3-a4d1e044715b","last_modified":1480349161763},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"VfTSum25nb65YPlpuhJAvg==","id":"91149dc9-6cc4-a670-1799-7bd05c159858","last_modified":1480349161740},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEwMC4GA1UEAxMnU3ltYW50ZWMgQ2xhc3MgMyBFQ0MgMjU2IGJpdCBFViBDQSAtIEcy","serialNumber":"OhrtngFwotLcm4i+z00SjA==","id":"337e2f4b-02c4-c70d-55be-09c8ea41731c","last_modified":1480349161718},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1181126","who":".","why":".","name":"RCS Certification Authority","created":"2015-07-13T09:05:40Z"},"enabled":true,"issuerName":"MDcxJDAiBgNVBAMTG1JDUyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEPMA0GA1UEChMGSFQgc3Js","serialNumber":"AN9bfYOvlR1t","id":"18c0d37b-739d-04c6-04f2-a615be5b9948","last_modified":1480349161696},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5BhENPfVw==","id":"72a65abf-9828-365f-4d4a-78457d7bdec4","last_modified":1480349161666},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESISuBo/wdW2tBztKmHdFCFz","id":"2ad44cbf-32ca-5245-c881-6d6f290ac2c1","last_modified":1480349161641},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1205651","who":".","why":".","name":"Misused certificate","created":"2015-09-21T13:21:25Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHjAcBgNVBAMTFXRoYXd0ZSBFViBTU0wgQ0EgLSBHMw==","serialNumber":"CrTHPEE6AZSfI3jysin2bA==","id":"13987e52-821e-1fe3-3743-393136b17167","last_modified":1480349161619},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMg==","serialNumber":"WX89jn8yGZVvoKTD9jDfRQ==","id":"a15c9fa5-cd6e-362d-1341-1e95c11c38fb","last_modified":1480349161596},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1252142","who":".","why":".","name":"exceptional SHA-1 Certificates","created":"2016-03-01T21:22:54Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"JV/LVzSKI/wsDgg3UuZHlA==","id":"ba7935ef-b624-3eef-5ae8-a78044ec3af0","last_modified":1480349161575},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:46Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"sPNcCSE9Nkg3jy5IN1xe2Q==","id":"edc761c4-8b47-5314-0cd1-c894612ebfc3","last_modified":1480349161553},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNQ==","serialNumber":"buROL/l2GuXISv+/JVLkdA==","id":"963548ca-bde2-1843-f140-1c26e8e40def","last_modified":1480349161531},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9oA==","id":"e85980d5-12f0-f624-7904-2d6cedeacd55","last_modified":1480349161510},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"IyIVazG4RE9AERkb+ekH8w==","id":"be3014a7-3d3b-08c7-02d9-5a74f601a1b1","last_modified":1480349161489},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"HNo1DR4XCe4mS1iUMsY6Wg==","id":"fd51f7d8-2006-663f-4779-3cf559ee5e74","last_modified":1480349161466},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"Ai7cBJYqBE0I9NdyoZfRrw==","id":"f7582bc8-dbdb-37dd-b24c-418242bbc4e0","last_modified":1480349161443},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"UUFV3S2cUidOOv7ESN65Ng==","id":"24ccf065-b88b-0fc9-1d1f-6c7722ca4faa","last_modified":1480349161103},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"EDQMI0tR4kSntv1O37N10g==","id":"e7509e16-1cd3-599e-2630-495ab52d3b71","last_modified":1480349161077},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:48:11Z"},"enabled":true,"issuerName":"MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB","serialNumber":"BAAAAAABI54PryQ=","id":"e3bd531e-1ee4-7407-27ce-6fdc9cecbbdc","last_modified":1480349161051},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byc68g==","id":"308f27b5-fc0e-da9a-2b7f-e65a1cb5cd47","last_modified":1480349161021},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEkMCIGA1UEAxMbU3ltYW50ZWMgQ2xhc3MgMyBEU0EgU1NMIENB","serialNumber":"AuhvPsYZfVP6UDsuyjeZ4Q==","id":"a0482eed-1e3f-7b9f-a433-94e4a4da49a1","last_modified":1480349160991},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:59Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABMrS7t2g=","id":"41a888b9-2e84-9782-69dc-d9153a3bd3aa","last_modified":1480349160963},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1197885","who":".","why":".","name":"SECOM intermediate certificate","created":"2016-07-21T16:52:32Z"},"enabled":true,"issuerName":"MFAxCzAJBgNVBAYTAkpQMRgwFgYDVQQKEw9TRUNPTSBUcnVzdC5uZXQxJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmljYXRpb24gUm9vdENBMQ==","serialNumber":"Ermwxw==","id":"1220feb9-9e66-0b24-3409-c5d1a1f8d24f","last_modified":1480349160941},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:36:53Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABCfhiO+s=","id":"e17ded97-6669-eecc-54fa-81f9a81ed281","last_modified":1480349160914},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1288354","who":".","why":".","name":"Symantec AATL ECC Intermediate CA cert","created":"2016-07-21T16:58:57Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA3IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNA==","serialNumber":"cXXMzbWDHMIdCotb3h64yw==","id":"a9970f7e-bac4-3b91-eae3-b0335ce0d1c2","last_modified":1480349160892},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"OqQ2rV0ISTc308Z/oQgzFw==","id":"781f8787-6508-d6aa-c508-13ac2bb0d930","last_modified":1480349160870},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cyr1PA==","id":"ec93f86d-fea2-7eea-42d4-7cf7a397e097","last_modified":1480349160848},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"F5Bg+EziQQ==","id":"64229466-b4da-c63f-e088-ab1b5ba37930","last_modified":1480349160826},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:09Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABEAuMoRs=","id":"fe2dd507-9fc4-a6db-7ee0-255452bea28a","last_modified":1480349160804},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:39:24Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHlSo=","id":"04460239-09d9-2a76-191e-f344a8e5d0bd","last_modified":1480349160782},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:08Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABKB/OGqI=","id":"6b5475ec-8181-e7b8-4245-c7e2ffed213c","last_modified":1480349160759},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESDu2nhlLPzfx+LYgjlYFP/k","id":"dc98c4eb-836f-6ca0-6673-6678fc45516a","last_modified":1480349160736},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1289808","who":".","why":".","name":"FNMT revoked intermediate certificates","created":"2016-07-28T12:14:46Z"},"enabled":true,"issuerName":"MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==","serialNumber":"BA==","id":"765f426d-748a-5f3d-e409-35eac9be8240","last_modified":1480349160714},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==","serialNumber":"Aw==","id":"644e3fde-7ab5-556a-85ef-c5fac8b8c7de","last_modified":1480349160684},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABMYnGRuw=","id":"0a9335d8-3fa3-5d0b-7b27-72ddd14b5f74","last_modified":1480349160660},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"Byd5cg==","id":"f046b001-5aa9-09b4-995d-23ad9f15db30","last_modified":1480349160638},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESJJweWBPhoXAaB9c8SHwI4O","id":"1bdc6228-2f9d-ad26-30b2-408959ede857","last_modified":1480349160614},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xMjAwBgNVBAMMKVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPcmdhbmlzYXRpZSBDQSAtIEcy","serialNumber":"LTRcDHabRHU=","id":"86e95439-a9f5-e04e-5241-268cf0186425","last_modified":1480349160593},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"YNOos6YJoPC77qwSGCpb7w==","id":"3c4f4898-da76-0a38-a765-18d9436285f2","last_modified":1480349160571},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHki0=","id":"e057bdab-4ad6-7e50-83ce-1099b84cce04","last_modified":1480349160547},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1286752","who":".","why":".","name":"Symantec erroneous SHA-1 certificates","created":"2016-07-14T14:40:23Z"},"enabled":true,"issuerName":"MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=","serialNumber":"A9GPKQ8jv9oIxfwiOy7qxQ==","id":"4bb8966b-1db9-844d-4904-d823539cdf7e","last_modified":1480349160524},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cbssdw==","id":"661e65a5-ee0b-7a82-12c3-731cb560e112","last_modified":1480349160216},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CcHC1w==","id":"26890617-93ad-e85f-550a-afb414cd110c","last_modified":1480349160190},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"DjIvBkX+ECVbB/C3i6w2Gg==","id":"657b91b1-9447-8c4a-db57-e0f0e2b10439","last_modified":1480349160165},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1150585","who":".","why":".","name":"XS4ALL certificate","created":"2015-04-07T11:04:11Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB","serialNumber":"UoRGnb96CUDTxIqVry6LBg==","id":"9084bc79-01cf-2ddc-b077-cd6c6251dd2b","last_modified":1480349160143},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"PAdKZPiaac2CvPxbOrsHOw==","id":"b79e2eb5-754d-4c21-1d8a-8c363f70dadc","last_modified":1480349160119},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIGQMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxOzA5BgNVBAMTMkFyaXN0b3RsZSBVbml2ZXJzaXR5IG9mIFRoZXNzYWxvbmlraSBDZW50cmFsIENBIFI0","serialNumber":"EqthLKdUgwI=","id":"5b9744a8-bd65-b926-2920-8d8e5e1acd7d","last_modified":1480349160086},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MGgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEiMCAGA1UEAxMZR2VvVHJ1c3QgRFYgU1NMIFNIQTI1NiBDQQ==","serialNumber":"OE4/d+p3YRzzcSl+kmZ8Mw==","id":"fd2fe6f3-d095-5c3d-3c6b-afe00cb665c0","last_modified":1480349160058},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==","serialNumber":"QZCrvA==","id":"32f968f5-4426-66ad-d1ab-9dda7b6f0c85","last_modified":1480349160028},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"AygWP2Fgd2T+iLbmAlKT6g==","id":"e23bcca2-1fb1-abd2-5ed7-892c5f08c4ff","last_modified":1480349159993},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"CqL7CA==","id":"1a0c71ac-7f34-eeb0-2f71-1c14ee8e6552","last_modified":1480349159963},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=","serialNumber":"E77H6yvyFQjO0PcN3x0H+Q==","id":"be9e31eb-6a06-7699-708a-732a081a10c7","last_modified":1480349159939},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:46:04Z"},"enabled":true,"issuerName":"MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==","serialNumber":"YRJNfMoc12IpmW+Enpv3Pdo=","id":"3bb8f2d9-511b-121d-da29-23041d3c15c1","last_modified":1480349159914},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155114","who":".","why":".","name":"Intermediate CA's under Staat der Nederlanden Root CA","created":"2015-05-08T10:54:05Z"},"enabled":true,"issuerName":"MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ==","serialNumber":"ATFEdg==","id":"4a17f132-602c-2d30-a781-145087794075","last_modified":1480349159890},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUaGF3dGUsIEluYy4xGzAZBgNVBAMTElRoYXd0ZSBTR0MgQ0EgLSBHMg==","serialNumber":"e0bEFhI16xx9U1yvlI56rA==","id":"07b97387-d755-0bbb-6e4c-616a7cb69cb4","last_modified":1480349159869},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"GN2Hrh9LtnA=","id":"b3fb394d-f951-b49e-d856-f93028850feb","last_modified":1480349159846},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAU=","id":"2448ada0-833d-0d4d-3bcd-2c73cff02fb4","last_modified":1480349159825},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:03Z"},"enabled":true,"issuerName":"MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==","serialNumber":"BAAAAAABCFiEp9s=","id":"5cef5dc2-95f2-0ac8-3273-153a09d3d227","last_modified":1480349159804},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CSY=","id":"b4c9041b-f5a5-dec1-b221-7286a32a6309","last_modified":1480349159782},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:44:06Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHJRKNmk=","id":"824e9b09-808e-e8cb-f2dd-ba669df011bc","last_modified":1480349159760},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=","serialNumber":"DYifRdP6aQQ8MLbXZY2f5g==","id":"59a292db-d567-6485-167f-1cb5af33f437","last_modified":1480349159739},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==","serialNumber":"BAAAAAABL07hTcY=","id":"0a5a0233-bb8a-e4cc-5bb6-03cee44a07c2","last_modified":1480349159716},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"L7tgs/W85vnhV7I7qJ6N/g==","id":"e38e4e46-413a-eac8-9e85-1b9ee06f535d","last_modified":1480349159694},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:40:36Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABLM/7qjk=","id":"62dfeb32-e132-09a3-e4ba-e48c21d027de","last_modified":1480349159673},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:41:41Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABHkSHjz8=","id":"880134d0-617c-ec1b-3568-4c74af31bcc1","last_modified":1480349159649},{"schema":1480349159276,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=","serialNumber":"Cfk9qg==","id":"9debdd66-d615-073f-26f7-011a8c54b484","last_modified":1480349159625},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAM=","id":"e4d16e1f-ac86-e9c0-2122-8a7d7d2dcdc0","last_modified":1480349159267},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESAyW/JX3+hZIp44EAMlXU2b","id":"6b135741-bfc6-1b3f-eb4b-4569aae2ab34","last_modified":1480349159244},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=","serialNumber":"AQAAAAQ=","id":"263f03a7-53f0-2140-89a5-46e7740d755a","last_modified":1480349159206},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESByYNtAIfizf2L3NMzCH8zZ","id":"853889e5-ad93-77ea-f9c0-a0907c9a3576","last_modified":1480349159183},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"BYOGvG32ukb1Yxj2oKoFyw==","id":"b049208e-5f4c-60a6-ac91-45f093defc33","last_modified":1480349159159},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzI=","serialNumber":"P6G7IYSL2RZxtzTh8I6qPA==","id":"222a4201-120e-64f4-5f6f-b2314470365c","last_modified":1480349159136},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:12Z"},"enabled":true,"issuerName":"MIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls","serialNumber":"D/wZ7+m1Mv8SONSEFcs73w==","id":"d7fdf5b8-f8a5-b105-297d-d0e3617e59fc","last_modified":1480349159113},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5","serialNumber":"eR1nUEz8k+nDSBD+bb5uIQ==","id":"f6fb7b44-64cd-37b9-b9f6-fbe1210cb160","last_modified":1480349159091},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:08Z"},"enabled":true,"issuerName":"MIG1MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS8wLQYDVQQDEyZWZXJpU2lnbiBDbGFzcyAzIFNlY3VyZSBTZXJ2ZXIgQ0EgLSBHMw==","serialNumber":"QZBvapTZFvmYktEPsBYLQQ==","id":"b6f5b3ee-6cac-57a7-b4e9-83e84f1020b8","last_modified":1480349159069},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABKUXDqA8=","id":"e48f4383-6df1-0a9b-8063-a2add391a879","last_modified":1480349159034},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=","serialNumber":"BAAAAAABLF5/Gog=","id":"bc0be7d5-b8d3-1ac2-8a63-f5bf8b00ba3c","last_modified":1480349159011},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=","serialNumber":"UW3oKZKTDsrPy/rfwmGNaQ==","id":"2a14bce1-47bb-e067-74a6-46be30e576a7","last_modified":1480349158980},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=","serialNumber":"CSU=","id":"77e152ae-89a4-53b1-62d4-fb7c2cd5037b","last_modified":1480349158957},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:14Z"},"enabled":true,"issuerName":"MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3Q=","serialNumber":"U3t2Vk8pfxTcaUPpIq0seQ==","id":"2c8f7191-fc5f-c2e0-af8d-852faefcdadf","last_modified":1480349158934},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","who":".","why":".","name":"GlobalSign certs","created":"2016-01-18T14:38:46Z"},"enabled":true,"issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","serialNumber":"BAAAAAABAPpuVh0=","id":"fce6cca1-707c-c4f2-6de2-26c4663cda01","last_modified":1480349158899},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==","serialNumber":"U4P1tUoxl/XkztlVHdtdgw==","id":"ed4d2530-eb3e-800f-41b2-e70023185673","last_modified":1480349158876},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MHsxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEsMCoGA1UEAxMjU3ltYW50ZWMgQ2xhc3MgMyBFQ0MgMjU2IGJpdCBTU0wgQ0E=","serialNumber":"U3SgRR3J+D6575WuCxuXeQ==","id":"72e44e74-fb5d-fc97-abdd-02050d3ab727","last_modified":1480349158854},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJzdC1IYXJkd2FyZQ==","serialNumber":"EEpERSryZFMagbsNw/WoWQ==","id":"a4f11626-67e9-24e5-81a5-aca8126934c3","last_modified":1480349158820},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu","serialNumber":"BAAAAAABJQcQQN0=","id":"e7328f54-0f56-48a2-3bab-d4c9b41a2b13","last_modified":1480349158794},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:11Z"},"enabled":true,"issuerName":"MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=","serialNumber":"BydKkg==","id":"6b9bc0cc-c1fa-50eb-5ece-812ee9bac5b6","last_modified":1480349158772},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:07Z"},"enabled":true,"issuerName":"MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==","serialNumber":"cpqpXVWPk5AXzGw+zNIcBw==","id":"ac8d05cd-d85d-8caa-ed13-261b83c183c2","last_modified":1480349158750},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1267648","who":".","why":".","name":"Symantec test certificates","created":"2016-04-28T21:08:06Z"},"enabled":true,"issuerName":"MGExCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEbMBkGA1UEAxMSR2VvVHJ1c3QgRFYgU1NMIENB","serialNumber":"CWhp","id":"ff01b36d-3bcc-2157-1f89-b1841120c97e","last_modified":1480349158726},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:13Z"},"enabled":true,"issuerName":"MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB","serialNumber":"ESCEUbthDurBjJw0/h/FfuNY","id":"2c047b2c-43aa-d0be-e2c9-2acac789bd55","last_modified":1480349158695},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1312150","who":".","why":".","name":"Revoked intermediates","created":"2016-10-27T17:52:10Z"},"enabled":true,"issuerName":"MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==","serialNumber":"TXxtAQ==","id":"ea4847df-ca17-c476-11df-b14c1d6658a0","last_modified":1480349158671},{"schema":1480343774567,"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1142137","who":".","why":".","name":"T-Systems intermediate cert","created":"2015-05-08T10:51:23Z"},"enabled":true,"issuerName":"MGcxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpGcmF1bmhvZmVyMSEwHwYDVQQLExhGcmF1bmhvZmVyIENvcnBvcmF0ZSBQS0kxIDAeBgNVBAMTF0ZyYXVuaG9mZXIgUm9vdCBDQSAyMDA3","serialNumber":"YR3YYQAAAAAABA==","id":"ae8bec3c-3b92-822e-53f1-68394cbb1758","last_modified":1480349158647}]} \ No newline at end of file diff --git a/crypto/x509/revocation/ocsp/ocsp.go b/crypto/x509/revocation/ocsp/ocsp.go deleted file mode 100644 index a17ff49d74a..00000000000 --- a/crypto/x509/revocation/ocsp/ocsp.go +++ /dev/null @@ -1,796 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses -// are signed messages attesting to the validity of a certificate for a small -// period of time. This is used to manage revocation for X.509 certificates. -package ocsp - -import ( - "errors" - "fmt" - "math/big" - "strconv" - "time" - - crypto "github.com/runZeroInc/excrypto/crypto" - - "crypto/rand" - - "github.com/runZeroInc/excrypto/crypto/ecdsa" - "github.com/runZeroInc/excrypto/crypto/elliptic" - "github.com/runZeroInc/excrypto/crypto/rsa" - _ "github.com/runZeroInc/excrypto/crypto/sha1" - _ "github.com/runZeroInc/excrypto/crypto/sha256" - _ "github.com/runZeroInc/excrypto/crypto/sha512" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/crypto/x509/revocation/crl" - "github.com/runZeroInc/excrypto/encoding/asn1" -) - -var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) - -// ResponseStatus contains the result of an OCSP request. See -// https://tools.ietf.org/html/rfc6960#section-2.3 -type ResponseStatus int - -const ( - Success ResponseStatus = 0 - Malformed ResponseStatus = 1 - InternalError ResponseStatus = 2 - TryLater ResponseStatus = 3 - // Status code four is unused in OCSP. See - // https://tools.ietf.org/html/rfc6960#section-4.2.1 - SignatureRequired ResponseStatus = 5 - Unauthorized ResponseStatus = 6 -) - -func (r ResponseStatus) String() string { - switch r { - case Success: - return "success" - case Malformed: - return "malformed" - case InternalError: - return "internal error" - case TryLater: - return "try later" - case SignatureRequired: - return "signature required" - case Unauthorized: - return "unauthorized" - default: - return "unknown OCSP status: " + strconv.Itoa(int(r)) - } -} - -// ResponseError is an error that may be returned by ParseResponse to indicate -// that the response itself is an error, not just that it's indicating that a -// certificate is revoked, unknown, etc. -type ResponseError struct { - Status ResponseStatus -} - -func (r ResponseError) Error() string { - return "ocsp: error from server: " + r.Status.String() -} - -// These are internal structures that reflect the ASN.1 structure of an OCSP -// response. See RFC 2560, section 4.2. - -type certID struct { - HashAlgorithm pkix.AlgorithmIdentifier - NameHash []byte - IssuerKeyHash []byte - SerialNumber *big.Int -} - -// https://tools.ietf.org/html/rfc2560#section-4.1.1 -type ocspRequest struct { - TBSRequest tbsRequest -} - -type tbsRequest struct { - Version int `asn1:"explicit,tag:0,default:0,optional"` - RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` - RequestList []request -} - -type request struct { - Cert certID -} - -type responseASN1 struct { - Status asn1.Enumerated - Response responseBytes `asn1:"explicit,tag:0,optional"` -} - -type responseBytes struct { - ResponseType asn1.ObjectIdentifier - Response []byte -} - -type basicResponse struct { - TBSResponseData responseData - SignatureAlgorithm pkix.AlgorithmIdentifier - Signature asn1.BitString - Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` -} - -type responseData struct { - Raw asn1.RawContent - Version int `asn1:"optional,default:0,explicit,tag:0"` - RawResponderID asn1.RawValue - ProducedAt time.Time `asn1:"generalized"` - Responses []singleResponse -} - -type singleResponse struct { - CertID certID - Good asn1.Flag `asn1:"tag:0,optional"` - Revoked revokedInfo `asn1:"tag:1,optional"` - Unknown asn1.Flag `asn1:"tag:2,optional"` - ThisUpdate time.Time `asn1:"generalized"` - NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` - SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` -} - -type revokedInfo struct { - RevocationTime time.Time `asn1:"generalized"` - Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` -} - -var ( - oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} - oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} - oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} - oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} - oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} - oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} - oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} - oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} - oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} - oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} - oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} - oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} -) - -var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ - crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), - crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), - crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), - crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), -} - -// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below -var signatureAlgorithmDetails = []struct { - algo x509.SignatureAlgorithm - oid asn1.ObjectIdentifier - pubKeyAlgo x509.PublicKeyAlgorithm - hash crypto.Hash -}{ - {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, - {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, - {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, - {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, - {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, - {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, - {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, - {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, - {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, - {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, - {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, - {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, -} - -// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below -func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { - var pubType x509.PublicKeyAlgorithm - - switch pub := pub.(type) { - case *rsa.PublicKey: - pubType = x509.RSA - hashFunc = crypto.SHA256 - sigAlgo.Algorithm = oidSignatureSHA256WithRSA - sigAlgo.Parameters = asn1.RawValue{ - Tag: 5, - } - - case *ecdsa.PublicKey: - pubType = x509.ECDSA - switch pub.Curve { - case elliptic.P224(), elliptic.P256(): - hashFunc = crypto.SHA256 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 - case elliptic.P384(): - hashFunc = crypto.SHA384 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 - case elliptic.P521(): - hashFunc = crypto.SHA512 - sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 - default: - err = errors.New("x509: unknown elliptic curve") - } - default: - err = errors.New("x509: only RSA and ECDSA keys supported") - } - - if err != nil { - return - } - - if requestedSigAlgo == 0 { - return - } - - found := false - for _, details := range signatureAlgorithmDetails { - if details.algo == requestedSigAlgo { - if details.pubKeyAlgo != pubType { - err = errors.New("x509: requested SignatureAlgorithm does not match private key type") - return - } - sigAlgo.Algorithm, hashFunc = details.oid, details.hash - if hashFunc == 0 { - err = errors.New("x509: cannot sign with hash function requested") - return - } - found = true - break - } - } - - if !found { - err = errors.New("x509: unknown SignatureAlgorithm") - } - - return -} - -// TODO(agl): this is taken from crypto/x509 and so should probably be exported -// from crypto/x509 or crypto/x509/pkix. -func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { - for _, details := range signatureAlgorithmDetails { - if oid.Equal(details.oid) { - return details.algo - } - } - return x509.UnknownSignatureAlgorithm -} - -// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. -func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { - for hash, oid := range hashOIDs { - if oid.Equal(target) { - return hash - } - } - return crypto.Hash(0) -} - -func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { - for hash, oid := range hashOIDs { - if hash == target { - return oid - } - } - return nil -} - -// This is the exposed reflection of the internal OCSP structures. - -// The status values that can be expressed in OCSP. See RFC 6960. -const ( - // Good means that the certificate is valid. - Good = iota - // Revoked means that the certificate has been deliberately revoked. - Revoked - // Unknown means that the OCSP responder doesn't know about the certificate. - Unknown - // ServerFailed is unused and was never used (see - // https://go-review.googlesource.com/#/c/18944). ParseResponse will - // return a ResponseError when an error response is parsed. - ServerFailed -) - -// The enumerated reasons for revoking a certificate. See RFC 5280. -const ( - Unspecified = 0 - KeyCompromise = 1 - CACompromise = 2 - AffiliationChanged = 3 - Superseded = 4 - CessationOfOperation = 5 - CertificateHold = 6 - - RemoveFromCRL = 8 - PrivilegeWithdrawn = 9 - AACompromise = 10 -) - -// Request represents an OCSP request. See RFC 6960. -type Request struct { - HashAlgorithm crypto.Hash - IssuerNameHash []byte - IssuerKeyHash []byte - SerialNumber *big.Int -} - -// Marshal marshals the OCSP request to ASN.1 DER encoded form. -func (req *Request) Marshal() ([]byte, error) { - hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) - if hashAlg == nil { - return nil, errors.New("Unknown hash algorithm") - } - return asn1.Marshal(ocspRequest{ - tbsRequest{ - Version: 0, - RequestList: []request{ - { - Cert: certID{ - pkix.AlgorithmIdentifier{ - Algorithm: hashAlg, - Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, - }, - req.IssuerNameHash, - req.IssuerKeyHash, - req.SerialNumber, - }, - }, - }, - }, - }) -} - -// Response represents an OCSP response containing a single SingleResponse. See -// RFC 6960. -type Response struct { - // Status is one of {Good, Revoked, Unknown} - Status int - SerialNumber *big.Int - IsRevoked bool // set to true if CertificateStatus is "revoked" - ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time - RevocationReason crl.RevocationReasonCode - Certificate *x509.Certificate - // TBSResponseData contains the raw bytes of the signed response. If - // Certificate is nil then this can be used to verify Signature. - TBSResponseData []byte - Signature []byte - SignatureAlgorithm x509.SignatureAlgorithm - - // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. - // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. - // If zero, the default is crypto.SHA1. - IssuerHash crypto.Hash - - // RawResponderName optionally contains the DER-encoded subject of the - // responder certificate. Exactly one of RawResponderName and - // ResponderKeyHash is set. - RawResponderName []byte - // ResponderKeyHash optionally contains the SHA-1 hash of the - // responder's public key. Exactly one of RawResponderName and - // ResponderKeyHash is set. - ResponderKeyHash []byte - - // Extensions contains raw X.509 extensions from the singleExtensions field - // of the OCSP response. When parsing certificates, this can be used to - // extract non-critical extensions that are not parsed by this package. When - // marshaling OCSP responses, the Extensions field is ignored, see - // ExtraExtensions. - Extensions []pkix.Extension - - // ExtraExtensions contains extensions to be copied, raw, into any marshaled - // OCSP response (in the singleExtensions field). Values override any - // extensions that would otherwise be produced based on the other fields. The - // ExtraExtensions field is not populated when parsing certificates, see - // Extensions. - ExtraExtensions []pkix.Extension -} - -// These are pre-serialized error responses for the various non-success codes -// defined by OCSP. The Unauthorized code in particular can be used by an OCSP -// responder that supports only pre-signed responses as a response to requests -// for certificates with unknown status. See RFC 5019. -var ( - MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} - InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} - TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} - SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} - UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} -) - -// CheckSignatureFrom checks that the signature in resp is a valid signature -// from issuer. This should only be used if resp.Certificate is nil. Otherwise, -// the OCSP response contained an intermediate certificate that created the -// signature. That signature is checked by ParseResponse and only -// resp.Certificate remains to be validated. -func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { - return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) -} - -// ParseError results from an invalid OCSP response. -type ParseError string - -func (p ParseError) Error() string { - return string(p) -} - -// ParseRequest parses an OCSP request in DER form. It only supports -// requests for a single certificate. Signed requests are not supported. -// If a request includes a signature, it will result in a ParseError. -func ParseRequest(bytes []byte) (*Request, error) { - var req ocspRequest - rest, err := asn1.Unmarshal(bytes, &req) - if err != nil { - return nil, err - } - if len(rest) > 0 { - return nil, ParseError("trailing data in OCSP request") - } - - if len(req.TBSRequest.RequestList) == 0 { - return nil, ParseError("OCSP request contains no request body") - } - innerRequest := req.TBSRequest.RequestList[0] - - hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) - if hashFunc == crypto.Hash(0) { - return nil, ParseError("OCSP request uses unknown hash function") - } - - return &Request{ - HashAlgorithm: hashFunc, - IssuerNameHash: innerRequest.Cert.NameHash, - IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, - SerialNumber: innerRequest.Cert.SerialNumber, - }, nil -} - -// ParseResponse parses an OCSP response in DER form. The response must contain -// only one certificate status. To parse the status of a specific certificate -// from a response which may contain multiple statuses, use ParseResponseForCert -// instead. -// -// If the response contains an embedded certificate, then that certificate will -// be used to verify the response signature. If the response contains an -// embedded certificate and issuer is not nil, then issuer will be used to verify -// the signature on the embedded certificate. -// -// If the response does not contain an embedded certificate and issuer is not -// nil, then issuer will be used to verify the response signature. -// -// Invalid responses and parse failures will result in a ParseError. -// Error responses will result in a ResponseError. -func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { - return ParseResponseForCert(bytes, nil, issuer) -} - -// ParseResponseForCert acts identically to ParseResponse, except it supports -// parsing responses that contain multiple statuses. If the response contains -// multiple statuses and cert is not nil, then ParseResponseForCert will return -// the first status which contains a matching serial, otherwise it will return an -// error. If cert is nil, then the first status in the response will be returned. -func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { - var resp responseASN1 - rest, err := asn1.Unmarshal(bytes, &resp) - if err != nil { - return nil, err - } - if len(rest) > 0 { - return nil, ParseError("trailing data in OCSP response") - } - - if status := ResponseStatus(resp.Status); status != Success { - return nil, ResponseError{status} - } - - if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { - return nil, ParseError("bad OCSP response type") - } - - var basicResp basicResponse - rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) - if err != nil { - return nil, err - } - if len(rest) > 0 { - return nil, ParseError("trailing data in OCSP response") - } - - if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { - return nil, ParseError("OCSP response contains bad number of responses") - } - - var singleResp singleResponse - if cert == nil { - singleResp = basicResp.TBSResponseData.Responses[0] - } else { - match := false - for _, resp := range basicResp.TBSResponseData.Responses { - if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { - singleResp = resp - match = true - break - } - } - if !match { - return nil, ParseError("no response matching the supplied certificate") - } - } - - ret := &Response{ - TBSResponseData: basicResp.TBSResponseData.Raw, - Signature: basicResp.Signature.RightAlign(), - SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), - Extensions: singleResp.SingleExtensions, - SerialNumber: singleResp.CertID.SerialNumber, - ProducedAt: basicResp.TBSResponseData.ProducedAt, - ThisUpdate: singleResp.ThisUpdate, - NextUpdate: singleResp.NextUpdate, - } - - // Handle the ResponderID CHOICE tag. ResponderID can be flattened into - // TBSResponseData once https://go-review.googlesource.com/34503 has been - // released. - rawResponderID := basicResp.TBSResponseData.RawResponderID - switch rawResponderID.Tag { - case 1: // Name - var rdn pkix.RDNSequence - if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { - return nil, ParseError("invalid responder name") - } - ret.RawResponderName = rawResponderID.Bytes - case 2: // KeyHash - if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { - return nil, ParseError("invalid responder key hash") - } - default: - return nil, ParseError("invalid responder id tag") - } - - if len(basicResp.Certificates) > 0 { - // Responders should only send a single certificate (if they - // send any) that connects the responder's certificate to the - // original issuer. We accept responses with multiple - // certificates due to a number responders sending them[1], but - // ignore all but the first. - // - // [1] https://github.com/golang/go/issues/21527 - ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) - if err != nil { - return nil, err - } - - if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { - return nil, ParseError("bad signature on embedded certificate: " + err.Error()) - } - - if issuer != nil { - if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { - return nil, ParseError("bad OCSP signature: " + err.Error()) - } - } - } else if issuer != nil { - if err := ret.CheckSignatureFrom(issuer); err != nil { - return nil, ParseError("bad OCSP signature: " + err.Error()) - } - } - - for _, ext := range singleResp.SingleExtensions { - if ext.Critical { - return nil, ParseError("unsupported critical extension") - } - } - - for h, oid := range hashOIDs { - if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { - ret.IssuerHash = h - break - } - } - if ret.IssuerHash == 0 { - return nil, ParseError("unsupported issuer hash algorithm") - } - - switch { - case bool(singleResp.Good): - ret.Status = Good - ret.IsRevoked = false - case bool(singleResp.Unknown): - ret.Status = Unknown - ret.IsRevoked = false - default: - ret.Status = Revoked - ret.IsRevoked = true - ret.RevokedAt = singleResp.Revoked.RevocationTime - ret.RevocationReason = crl.RevocationReasonCode(singleResp.Revoked.Reason) - } - - return ret, nil -} - -// RequestOptions contains options for constructing OCSP requests. -type RequestOptions struct { - // Hash contains the hash function that should be used when - // constructing the OCSP request. If zero, SHA-1 will be used. - Hash crypto.Hash -} - -func (opts *RequestOptions) hash() crypto.Hash { - if opts == nil || opts.Hash == 0 { - // SHA-1 is nearly universally used in OCSP. - return crypto.SHA1 - } - return opts.Hash -} - -// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If -// opts is nil then sensible defaults are used. -func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { - hashFunc := opts.hash() - - // OCSP seems to be the only place where these raw hash identifiers are - // used. I took the following from - // http://msdn.microsoft.com/en-us/library/ff635603.aspx - _, ok := hashOIDs[hashFunc] - if !ok { - return nil, x509.ErrUnsupportedAlgorithm - } - - if !hashFunc.Available() { - return nil, x509.ErrUnsupportedAlgorithm - } - h := opts.hash().New() - - var publicKeyInfo struct { - Algorithm pkix.AlgorithmIdentifier - PublicKey asn1.BitString - } - if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { - return nil, err - } - - h.Write(publicKeyInfo.PublicKey.RightAlign()) - issuerKeyHash := h.Sum(nil) - - h.Reset() - h.Write(issuer.RawSubject) - issuerNameHash := h.Sum(nil) - - req := &Request{ - HashAlgorithm: hashFunc, - IssuerNameHash: issuerNameHash, - IssuerKeyHash: issuerKeyHash, - SerialNumber: cert.SerialNumber, - } - return req.Marshal() -} - -// CreateResponse returns a DER-encoded OCSP response with the specified contents. -// The fields in the response are populated as follows: -// -// The responder cert is used to populate the responder's name field, and the -// certificate itself is provided alongside the OCSP response signature. -// -// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. -// -// The template is used to populate the SerialNumber, Status, RevokedAt, -// RevocationReason, ThisUpdate, and NextUpdate fields. -// -// If template.IssuerHash is not set, SHA1 will be used. -// -// The ProducedAt date is automatically set to the current date, to the nearest minute. -func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { - var publicKeyInfo struct { - Algorithm pkix.AlgorithmIdentifier - PublicKey asn1.BitString - } - if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { - return nil, err - } - - if template.IssuerHash == 0 { - template.IssuerHash = crypto.SHA1 - } - hashOID := getOIDFromHashAlgorithm(template.IssuerHash) - if hashOID == nil { - return nil, errors.New("unsupported issuer hash algorithm") - } - - if !template.IssuerHash.Available() { - return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) - } - h := template.IssuerHash.New() - h.Write(publicKeyInfo.PublicKey.RightAlign()) - issuerKeyHash := h.Sum(nil) - - h.Reset() - h.Write(issuer.RawSubject) - issuerNameHash := h.Sum(nil) - - innerResponse := singleResponse{ - CertID: certID{ - HashAlgorithm: pkix.AlgorithmIdentifier{ - Algorithm: hashOID, - Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, - }, - NameHash: issuerNameHash, - IssuerKeyHash: issuerKeyHash, - SerialNumber: template.SerialNumber, - }, - ThisUpdate: template.ThisUpdate.UTC(), - NextUpdate: template.NextUpdate.UTC(), - SingleExtensions: template.ExtraExtensions, - } - - switch template.Status { - case Good: - innerResponse.Good = true - case Unknown: - innerResponse.Unknown = true - case Revoked: - innerResponse.Revoked = revokedInfo{ - RevocationTime: template.RevokedAt.UTC(), - Reason: asn1.Enumerated(template.RevocationReason), - } - } - - rawResponderID := asn1.RawValue{ - Class: 2, // context-specific - Tag: 1, // Name (explicit tag) - IsCompound: true, - Bytes: responderCert.RawSubject, - } - tbsResponseData := responseData{ - Version: 0, - RawResponderID: rawResponderID, - ProducedAt: time.Now().Truncate(time.Minute).UTC(), - Responses: []singleResponse{innerResponse}, - } - - tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) - if err != nil { - return nil, err - } - - hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) - if err != nil { - return nil, err - } - - responseHash := hashFunc.New() - responseHash.Write(tbsResponseDataDER) - signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) - if err != nil { - return nil, err - } - - response := basicResponse{ - TBSResponseData: tbsResponseData, - SignatureAlgorithm: signatureAlgorithm, - Signature: asn1.BitString{ - Bytes: signature, - BitLength: 8 * len(signature), - }, - } - if template.Certificate != nil { - response.Certificates = []asn1.RawValue{ - {FullBytes: template.Certificate.Raw}, - } - } - responseDER, err := asn1.Marshal(response) - if err != nil { - return nil, err - } - - return asn1.Marshal(responseASN1{ - Status: asn1.Enumerated(Success), - Response: responseBytes{ - ResponseType: idPKIXOCSPBasic, - Response: responseDER, - }, - }) -} diff --git a/crypto/x509/revocation/ocsp/ocsp_test.go b/crypto/x509/revocation/ocsp/ocsp_test.go deleted file mode 100644 index cb47d09b83a..00000000000 --- a/crypto/x509/revocation/ocsp/ocsp_test.go +++ /dev/null @@ -1,881 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.7 -// +build go1.7 - -package ocsp - -import ( - "bytes" - "encoding/hex" - "math/big" - "reflect" - "testing" - "time" - - crypto "github.com/runZeroInc/excrypto/crypto" - - "github.com/runZeroInc/excrypto/crypto/sha1" - - "github.com/runZeroInc/excrypto/crypto/x509" - "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/encoding/asn1" -) - -func TestOCSPDecode(t *testing.T) { - responseBytes, _ := hex.DecodeString(ocspResponseHex) - resp, err := ParseResponse(responseBytes, nil) - if err != nil { - t.Fatal(err) - } - - responderCert, _ := hex.DecodeString(startComResponderCertHex) - responder, err := x509.ParseCertificate(responderCert) - if err != nil { - t.Fatal(err) - } - - expected := Response{ - Status: Good, - SerialNumber: big.NewInt(0x1d0fa), - RevocationReason: Unspecified, - ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC), - NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC), - RawResponderName: responder.RawSubject, - } - - if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { - t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate) - } - - if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) { - t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate) - } - - if resp.Status != expected.Status { - t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status) - } - - if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 { - t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber) - } - - if resp.RevocationReason != expected.RevocationReason { - t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason) - } - - if !bytes.Equal(resp.RawResponderName, expected.RawResponderName) { - t.Errorf("resp.RawResponderName: got %x, want %x", resp.RawResponderName, expected.RawResponderName) - } - - if !bytes.Equal(resp.ResponderKeyHash, expected.ResponderKeyHash) { - t.Errorf("resp.ResponderKeyHash: got %x, want %x", resp.ResponderKeyHash, expected.ResponderKeyHash) - } -} - -func TestOCSPDecodeWithoutCert(t *testing.T) { - responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) - _, err := ParseResponse(responseBytes, nil) - if err != nil { - t.Error(err) - } -} - -func TestOCSPDecodeWithExtensions(t *testing.T) { - responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex) - _, err := ParseResponse(responseBytes, nil) - if err == nil { - t.Error(err) - } - - responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex) - response, err := ParseResponse(responseBytes, nil) - if err != nil { - t.Fatal(err) - } - - if len(response.Extensions) != 1 { - t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1) - } - - extensionBytes := response.Extensions[0].Value - expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex) - if !bytes.Equal(extensionBytes, expectedBytes) { - t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes) - } -} - -func TestOCSPSignature(t *testing.T) { - issuerCert, _ := hex.DecodeString(startComHex) - issuer, err := x509.ParseCertificate(issuerCert) - if err != nil { - t.Fatal(err) - } - - response, _ := hex.DecodeString(ocspResponseHex) - if _, err := ParseResponse(response, issuer); err != nil { - t.Error(err) - } -} - -func TestOCSPRequest(t *testing.T) { - leafCert, _ := hex.DecodeString(leafCertHex) - cert, err := x509.ParseCertificate(leafCert) - if err != nil { - t.Fatal(err) - } - - issuerCert, _ := hex.DecodeString(issuerCertHex) - issuer, err := x509.ParseCertificate(issuerCert) - if err != nil { - t.Fatal(err) - } - - request, err := CreateRequest(cert, issuer, nil) - if err != nil { - t.Fatal(err) - } - - expectedBytes, _ := hex.DecodeString(ocspRequestHex) - if !bytes.Equal(request, expectedBytes) { - t.Errorf("request: got %x, wanted %x", request, expectedBytes) - } - - decodedRequest, err := ParseRequest(expectedBytes) - if err != nil { - t.Fatal(err) - } - - if decodedRequest.HashAlgorithm != crypto.SHA1 { - t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1) - } - - var publicKeyInfo struct { - Algorithm pkix.AlgorithmIdentifier - PublicKey asn1.BitString - } - _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo) - if err != nil { - t.Fatal(err) - } - - h := sha1.New() - h.Write(publicKeyInfo.PublicKey.RightAlign()) - issuerKeyHash := h.Sum(nil) - - h.Reset() - h.Write(issuer.RawSubject) - issuerNameHash := h.Sum(nil) - - if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) { - t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash) - } - - if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) { - t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash) - } - - if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 { - t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber) - } - - marshaledRequest, err := decodedRequest.Marshal() - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(expectedBytes, marshaledRequest) { - t.Errorf( - "Marshaled request doesn't match expected: wanted %x, got %x", - expectedBytes, - marshaledRequest, - ) - } -} - -func TestOCSPResponse(t *testing.T) { - leafCert, _ := hex.DecodeString(leafCertHex) - leaf, err := x509.ParseCertificate(leafCert) - if err != nil { - t.Fatal(err) - } - - issuerCert, _ := hex.DecodeString(issuerCertHex) - issuer, err := x509.ParseCertificate(issuerCert) - if err != nil { - t.Fatal(err) - } - - responderCert, _ := hex.DecodeString(responderCertHex) - responder, err := x509.ParseCertificate(responderCert) - if err != nil { - t.Fatal(err) - } - - responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex) - responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER) - if err != nil { - t.Fatal(err) - } - - extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex) - extensions := []pkix.Extension{ - { - Id: ocspExtensionOID, - Critical: false, - Value: extensionBytes, - }, - } - - thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC) - nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC) - template := Response{ - Status: Revoked, - SerialNumber: leaf.SerialNumber, - ThisUpdate: thisUpdate, - NextUpdate: nextUpdate, - RevokedAt: thisUpdate, - RevocationReason: KeyCompromise, - Certificate: responder, - ExtraExtensions: extensions, - } - - template.IssuerHash = crypto.MD5 - _, err = CreateResponse(issuer, responder, template, responderPrivateKey) - if err == nil { - t.Fatal("CreateResponse didn't fail with non-valid template.IssuerHash value crypto.MD5") - } - - testCases := []struct { - name string - issuerHash crypto.Hash - }{ - {"Zero value", 0}, - {"crypto.SHA1", crypto.SHA1}, - {"crypto.SHA256", crypto.SHA256}, - {"crypto.SHA384", crypto.SHA384}, - {"crypto.SHA512", crypto.SHA512}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - template.IssuerHash = tc.issuerHash - responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey) - if err != nil { - t.Fatalf("CreateResponse failed: %s", err) - } - - resp, err := ParseResponse(responseBytes, nil) - if err != nil { - t.Fatalf("ParseResponse failed: %s", err) - } - - if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) { - t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, template.ThisUpdate) - } - - if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) { - t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, template.NextUpdate) - } - - if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) { - t.Errorf("resp.RevokedAt: got %v, want %v", resp.RevokedAt, template.RevokedAt) - } - - if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) { - t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions) - } - - delay := time.Since(resp.ProducedAt) - if delay < -time.Hour || delay > time.Hour { - t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now()) - } - - if resp.Status != template.Status { - t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status) - } - - if resp.SerialNumber.Cmp(template.SerialNumber) != 0 { - t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber) - } - - if resp.RevocationReason != template.RevocationReason { - t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason) - } - - expectedHash := tc.issuerHash - if tc.issuerHash == 0 { - expectedHash = crypto.SHA1 - } - - if resp.IssuerHash != expectedHash { - t.Errorf("resp.IssuerHash: got %d, want %d", resp.IssuerHash, expectedHash) - } - }) - } -} - -func TestErrorResponse(t *testing.T) { - responseBytes, _ := hex.DecodeString(errorResponseHex) - _, err := ParseResponse(responseBytes, nil) - - respErr, ok := err.(ResponseError) - if !ok { - t.Fatalf("expected ResponseError from ParseResponse but got %#v", err) - } - if respErr.Status != Malformed { - t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status) - } -} - -func TestOCSPDecodeMultiResponse(t *testing.T) { - inclCert, _ := hex.DecodeString(ocspMultiResponseCertHex) - cert, err := x509.ParseCertificate(inclCert) - if err != nil { - t.Fatal(err) - } - - responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) - resp, err := ParseResponseForCert(responseBytes, cert, nil) - if err != nil { - t.Fatal(err) - } - - if resp.SerialNumber.Cmp(cert.SerialNumber) != 0 { - t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, cert.SerialNumber) - } -} - -func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) { - wrongCert, _ := hex.DecodeString(startComHex) - cert, err := x509.ParseCertificate(wrongCert) - if err != nil { - t.Fatal(err) - } - - responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) - _, err = ParseResponseForCert(responseBytes, cert, nil) - want := ParseError("no response matching the supplied certificate") - if err != want { - t.Errorf("err: got %q, want %q", err, want) - } -} - -// This OCSP response was taken from Thawte's public OCSP responder. -// To recreate: -// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443 -// Copy and paste the first certificate into /tmp/cert.crt and the second into -// /tmp/intermediate.crt -// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der -// Then hex encode the result: -// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' - -const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" + - "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" + - "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" + - "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" + - "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" + - "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" + - "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" + - "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" + - "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" + - "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" + - "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" + - "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" + - "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" + - "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" + - "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" + - "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" + - "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" + - "69676974616c204365727469666963617465205369676e696e6731383036060355040313" + - "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" + - "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" + - "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" + - "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" + - "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" + - "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" + - "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" + - "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" + - "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" + - "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" + - "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" + - "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" + - "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" + - "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" + - "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" + - "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" + - "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" + - "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" + - "4469676974616c204365727469666963617465205369676e696e67312930270603550403" + - "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" + - "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" + - "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" + - "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" + - "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" + - "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" + - "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" + - "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" + - "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" + - "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" + - "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42" - -const startComResponderCertHex = "308204b23082039aa003020102020101300d06092a864886f70d010105050030818c310b" + - "300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e31" + - "2b3029060355040b1322536563757265204469676974616c204365727469666963617465" + - "205369676e696e67313830360603550403132f5374617274436f6d20436c617373203120" + - "5072696d61727920496e7465726d65646961746520536572766572204341301e170d3037" + - "313032353030323330365a170d3132313032333030323330365a304c310b300906035504" + - "061302494c31163014060355040a130d5374617274436f6d204c74642e31253023060355" + - "0403131c5374617274436f6d20436c6173732031204f435350205369676e657230820122" + - "300d06092a864886f70d01010105000382010f003082010a0282010100b9561b4c453187" + - "17178084e96e178df2255e18ed8d8ecc7c2b7b51a6c1c2e6bf0aa3603066f132fe10ae97" + - "b50e99fa24b83fc53dd2777496387d14e1c3a9b6a4933e2ac12413d085570a95b8147414" + - "a0bc007c7bcf222446ef7f1a156d7ea1c577fc5f0facdfd42eb0f5974990cb2f5cefebce" + - "ef4d1bdc7ae5c1075c5a99a93171f2b0845b4ff0864e973fcfe32f9d7511ff87a3e94341" + - "0c90a4493a306b6944359340a9ca96f02b66ce67f028df2980a6aaee8d5d5d452b8b0eb9" + - "3f923cc1e23fcccbdbe7ffcb114d08fa7a6a3c404f825d1a0e715935cf623a8c7b596700" + - "14ed0622f6089a9447a7a19010f7fe58f84129a2765ea367824d1c3bb2fda30853020301" + - "0001a382015c30820158300c0603551d130101ff04023000300b0603551d0f0404030203" + - "a8301e0603551d250417301506082b0601050507030906092b0601050507300105301d06" + - "03551d0e0416041445e0a36695414c5dd449bc00e33cdcdbd2343e173081a80603551d23" + - "0481a030819d8014eb4234d098b0ab9ff41b6b08f7cc642eef0e2c45a18181a47f307d31" + - "0b300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e" + - "312b3029060355040b1322536563757265204469676974616c2043657274696669636174" + - "65205369676e696e6731293027060355040313205374617274436f6d2043657274696669" + - "636174696f6e20417574686f7269747982010a30230603551d12041c301a861868747470" + - "3a2f2f7777772e737461727473736c2e636f6d2f302c06096086480186f842010d041f16" + - "1d5374617274436f6d205265766f636174696f6e20417574686f72697479300d06092a86" + - "4886f70d01010505000382010100182d22158f0fc0291324fa8574c49bb8ff2835085adc" + - "bf7b7fc4191c397ab6951328253fffe1e5ec2a7da0d50fca1a404e6968481366939e666c" + - "0a6209073eca57973e2fefa9ed1718e8176f1d85527ff522c08db702e3b2b180f1cbff05" + - "d98128252cf0f450f7dd2772f4188047f19dc85317366f94bc52d60f453a550af58e308a" + - "aab00ced33040b62bf37f5b1ab2a4f7f0f80f763bf4d707bc8841d7ad9385ee2a4244469" + - "260b6f2bf085977af9074796048ecc2f9d48a1d24ce16e41a9941568fec5b42771e118f1" + - "6c106a54ccc339a4b02166445a167902e75e6d8620b0825dcd18a069b90fd851d10fa8ef" + - "fd409deec02860d26d8d833f304b10669b42" - -const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + - "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + - "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + - "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + - "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + - "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + - "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + - "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + - "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + - "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + - "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + - "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + - "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + - "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + - "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + - "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + - "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + - "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + - "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + - "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + - "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + - "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + - "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + - "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + - "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + - "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + - "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + - "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + - "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + - "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + - "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + - "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + - "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + - "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + - "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + - "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + - "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + - "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + - "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + - "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + - "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + - "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + - "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + - "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + - "d2ae83a7a8ce5ba7" - -const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + - "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + - "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" + - "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" + - "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" + - "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" + - "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" + - "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" + - "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" + - "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" + - "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" + - "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" + - "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + - "5a35fca2e054dfa8" - -// PKIX nonce extension -var ( - ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2} - ocspExtensionValueHex = "0403000000" -) - -const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" + - "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + - "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" + - "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + - "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + - "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + - "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" + - "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" + - "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" + - "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" + - "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" + - "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" + - "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" + - "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" + - "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" + - "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + - "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + - "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + - "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + - "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + - "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + - "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + - "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + - "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + - "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + - "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + - "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + - "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + - "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + - "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + - "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + - "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + - "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + - "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + - "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + - "3a25439a94299a65a709756c7a3e568be049d5c38839" - -const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" + - "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + - "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" + - "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + - "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + - "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + - "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" + - "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" + - "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" + - "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" + - "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" + - "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" + - "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" + - "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" + - "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" + - "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" + - "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" + - "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" + - "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" + - "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" + - "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" + - "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" + - "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" + - "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" + - "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" + - "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" + - "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" + - "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" + - "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" + - "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" + - "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" + - "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" + - "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" + - "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" + - "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + - "9a94299a65a709756c7a3e568be049d5c38839" - -const ocspMultiResponseHex = "30820ee60a0100a0820edf30820edb06092b060105050730010104820ecc30820ec83082" + - "0839a216041445ac2ecd75f53f1cf6e4c51d3de0047ad0aa7465180f3230313530363032" + - "3130303033305a3082080c3065303d300906052b0e03021a05000414f7452a0080601527" + - "72e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204" + - "5456656a8000180f32303135303630323039303230375aa011180f323031353036303331" + - "30303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e7" + - "6e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656b80" + - "00180f32303135303630323039303230375aa011180f3230313530363033313030303330" + - "5a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0" + - "f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656c8000180f3230" + - "3135303630323039303230375aa011180f32303135303630333130303033305a3065303d" + - "300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414ed" + - "d8f2ee977252853a330b297a18f5c993853b3f02045456656d8000180f32303135303630" + - "323039303230375aa011180f32303135303630333130303033305a3065303d300906052b" + - "0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee9772" + - "52853a330b297a18f5c993853b3f02045456656e8000180f323031353036303230393032" + - "30375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a05" + - "000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b" + - "297a18f5c993853b3f02045456656f8000180f32303135303630323039303230375aa011" + - "180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f745" + - "2a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c9" + - "93853b3f0204545665708000180f32303135303630323039303230375aa011180f323031" + - "35303630333130303033305a3065303d300906052b0e03021a05000414f7452a00806015" + - "2772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02" + - "04545665718000180f32303135303630323039303230375aa011180f3230313530363033" + - "3130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135" + - "e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f020454566572" + - "8000180f32303135303630323039303230375aa011180f32303135303630333130303033" + - "305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fd" + - "e0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665738000180f32" + - "303135303630323039303230375aa011180f32303135303630333130303033305a306530" + - "3d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414" + - "edd8f2ee977252853a330b297a18f5c993853b3f0204545665748000180f323031353036" + - "30323039303230375aa011180f32303135303630333130303033305a3065303d30090605" + - "2b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee97" + - "7252853a330b297a18f5c993853b3f0204545665758000180f3230313530363032303930" + - "3230375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a" + - "05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a33" + - "0b297a18f5c993853b3f0204545665768000180f32303135303630323039303230375aa0" + - "11180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f7" + - "452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5" + - "c993853b3f0204545665778000180f32303135303630323039303230375aa011180f3230" + - "3135303630333130303033305a3065303d300906052b0e03021a05000414f7452a008060" + - "152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f" + - "0204545665788000180f32303135303630323039303230375aa011180f32303135303630" + - "333130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a1" + - "35e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665" + - "798000180f32303135303630323039303230375aa011180f323031353036303331303030" + - "33305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52" + - "fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456657a8000180f" + - "32303135303630323039303230375aa011180f32303135303630333130303033305a3065" + - "303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f15804" + - "14edd8f2ee977252853a330b297a18f5c993853b3f02045456657b8000180f3230313530" + - "3630323039303230375aa011180f32303135303630333130303033305a3065303d300906" + - "052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee" + - "977252853a330b297a18f5c993853b3f02045456657c8000180f32303135303630323039" + - "303230375aa011180f32303135303630333130303033305a3065303d300906052b0e0302" + - "1a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a" + - "330b297a18f5c993853b3f02045456657d8000180f32303135303630323039303230375a" + - "a011180f32303135303630333130303033305a300d06092a864886f70d01010505000382" + - "01010016b73b92859979f27d15eb018cf069eed39c3d280213565f3026de11ba15bdb94d" + - "764cf2d0fdd204ef926c588d7b183483c8a2b1995079c7ed04dcefcc650c1965be4b6832" + - "a8839e832f7f60f638425eccdf9bc3a81fbe700fda426ddf4f06c29bee431bbbe81effda" + - "a60b7da5b378f199af2f3c8380be7ba6c21c8e27124f8a4d8989926aea19055700848d33" + - "799e833512945fd75364edbd2dd18b783c1e96e332266b17979a0b88c35b43f47c87c493" + - "19155056ad8dbbae5ff2afad3c0e1c69ed111206ffda49875e8e4efc0926264823bc4423" + - "c8a002f34288c4bc22516f98f54fc609943721f590ddd8d24f989457526b599b0eb75cb5" + - "a80da1ad93a621a08205733082056f3082056b30820453a0030201020204545638c4300d" + - "06092a864886f70d01010b0500308182310b300906035504061302555331183016060355" + - "040a130f552e532e20476f7665726e6d656e7431233021060355040b131a446570617274" + - "6d656e74206f662074686520547265617375727931223020060355040b13194365727469" + - "6669636174696f6e20417574686f7269746965733110300e060355040b13074f43494f20" + - "4341301e170d3135303332303131353531335a170d3135303633303034303030305a3081" + - "98310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + - "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + - "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + - "69746965733110300e060355040b13074f43494f204341311430120603550403130b4f43" + - "5350205369676e657230820122300d06092a864886f70d01010105000382010f00308201" + - "0a0282010100c1b6fe1ba1ad50bb98c855811acbd67fe68057f48b8e08d3800e7f2c51b7" + - "9e20551934971fd92b9c9e6c49453097927cba83a94c0b2fea7124ba5ac442b38e37dba6" + - "7303d4962dd7d92b22a04b0e0e182e9ea67620b1c6ce09ee607c19e0e6e3adae81151db1" + - "2bb7f706149349a292e21c1eb28565b6839df055e1a838a772ff34b5a1452618e2c26042" + - "705d53f0af4b57aae6163f58216af12f3887813fe44b0321827b3a0c52b0e47d0aab94a2" + - "f768ab0ba3901d22f8bb263823090b0e37a7f8856db4b0d165c42f3aa7e94f5f6ce1855e" + - "98dc57adea0ae98ad39f67ecdec00b88685566e9e8d69f6cefb6ddced53015d0d3b862bc" + - "be21f3d72251eefcec730203010001a38201cf308201cb300e0603551d0f0101ff040403" + - "020780306b0603551d2004643062300c060a60864801650302010502300c060a60864801" + - "650302010503300c060a60864801650302010504300c060a60864801650302010507300c" + - "060a60864801650302010508300c060a6086480165030201030d300c060a608648016503" + - "020103113081e506082b060105050701010481d83081d5303006082b0601050507300286" + - "24687474703a2f2f706b692e74726561732e676f762f746f63615f65655f6169612e7037" + - "633081a006082b060105050730028681936c6461703a2f2f6c6461702e74726561732e67" + - "6f762f6f753d4f43494f25323043412c6f753d43657274696669636174696f6e25323041" + - "7574686f7269746965732c6f753d4465706172746d656e742532306f6625323074686525" + - "323054726561737572792c6f3d552e532e253230476f7665726e6d656e742c633d55533f" + - "634143657274696669636174653b62696e61727930130603551d25040c300a06082b0601" + - "0505070309300f06092b060105050730010504020500301f0603551d23041830168014a2" + - "13a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e0416041451f98046818a" + - "e46d953ac90c210ccfaa1a06980c300d06092a864886f70d01010b050003820101003a37" + - "0b301d14ffdeb370883639bec5ae6f572dcbddadd672af16ee2a8303316b14e1fbdca8c2" + - "8f4bad9c7b1410250e149c14e9830ca6f17370a8d13151205d956e28c141cc0500379596" + - "c5b9239fcfa3d2de8f1d4f1a2b1bf2d1851bed1c86012ee8135bdc395cd4496ce69fadd0" + - "3b682b90350ca7b4f458190b7a0ab5c33a04cf1347a77d541877a380a4c94988c5658908" + - "44fdc22637a72b9fa410333e2caf969477f9fe07f50e3681c204fb3bf073b9da01cd8d91" + - "8044c40b1159955af12a3263ab1d34119d7f59bfa6cae88ed058addc4e08250263f8f836" + - "2f5bdffd45636fea7474c60a55c535954477b2f286e1b2535f0dd12c162f1b353c370e08" + - "be67" - -const ocspMultiResponseCertHex = "308207943082067ca003020102020454566573300d06092a864886f70d01010b05003081" + - "82310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + - "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + - "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + - "69746965733110300e060355040b13074f43494f204341301e170d313530343130313535" + - "3733385a170d3138303431303136323733385a30819d310b300906035504061302555331" + - "183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b131a" + - "4465706172746d656e74206f662074686520547265617375727931253023060355040b13" + - "1c427572656175206f66207468652046697363616c20536572766963653110300e060355" + - "040b130744657669636573311630140603550403130d706b692e74726561732e676f7630" + - "820122300d06092a864886f70d01010105000382010f003082010a0282010100c7273623" + - "8c49c48bf501515a2490ef6e5ae0c06e0ad2aa9a6bb77f3d0370d846b2571581ebf38fd3" + - "1948daad3dec7a4da095f1dcbe9654e65bcf7acdfd4ee802421dad9b90536c721d2bca58" + - "8413e6bfd739a72470560bb7d64f9a09284f90ff8af1d5a3c5c84d0f95a00f9c6d988dd0" + - "d87f1d0d3344580901c955139f54d09de0acdbd3322b758cb0c58881bf04913243401f44" + - "013fd9f6d8348044cc8bb0a71978ad93366b2a4687a5274b2ee07d0fb40225453eb244ed" + - "b20152251ac77c59455260ff07eeceb3cb3c60fb8121cf92afd3daa2a4650e1942ccb555" + - "de10b3d481feb299838ef05d0fd1810b146753472ae80da65dd34da25ca1f89971f10039" + - "0203010001a38203f3308203ef300e0603551d0f0101ff0404030205a030170603551d20" + - "0410300e300c060a60864801650302010503301106096086480186f84201010404030206" + - "4030130603551d25040c300a06082b060105050703013082010806082b06010505070101" + - "0481fb3081f8303006082b060105050730028624687474703a2f2f706b692e7472656173" + - "2e676f762f746f63615f65655f6169612e7037633081a006082b06010505073002868193" + - "6c6461703a2f2f6c6461702e74726561732e676f762f6f753d4f43494f25323043412c6f" + - "753d43657274696669636174696f6e253230417574686f7269746965732c6f753d446570" + - "6172746d656e742532306f6625323074686525323054726561737572792c6f3d552e532e" + - "253230476f7665726e6d656e742c633d55533f634143657274696669636174653b62696e" + - "617279302106082b060105050730018615687474703a2f2f6f6373702e74726561732e67" + - "6f76307b0603551d1104743072811c6373612d7465616d4066697363616c2e7472656173" + - "7572792e676f768210706b692e74726561737572792e676f768210706b692e64696d632e" + - "6468732e676f76820d706b692e74726561732e676f76811f6563622d686f7374696e6740" + - "66697363616c2e74726561737572792e676f76308201890603551d1f048201803082017c" + - "3027a025a0238621687474703a2f2f706b692e74726561732e676f762f4f43494f5f4341" + - "332e63726c3082014fa082014ba0820147a48197308194310b3009060355040613025553" + - "31183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b13" + - "1a4465706172746d656e74206f662074686520547265617375727931223020060355040b" + - "131943657274696669636174696f6e20417574686f7269746965733110300e060355040b" + - "13074f43494f2043413110300e0603550403130743524c313430398681aa6c6461703a2f" + - "2f6c6461702e74726561732e676f762f636e3d43524c313430392c6f753d4f43494f2532" + - "3043412c6f753d43657274696669636174696f6e253230417574686f7269746965732c6f" + - "753d4465706172746d656e742532306f6625323074686525323054726561737572792c6f" + - "3d552e532e253230476f7665726e6d656e742c633d55533f636572746966696361746552" + - "65766f636174696f6e4c6973743b62696e617279302b0603551d1004243022800f323031" + - "35303431303135353733385a810f32303138303431303136323733385a301f0603551d23" + - "041830168014a213a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e041604" + - "14b0869c12c293914cd460e33ed43e6c5a26e0d68f301906092a864886f67d074100040c" + - "300a1b0456382e31030203a8300d06092a864886f70d01010b050003820101004968d182" + - "8f9efdc147e747bb5dda15536a42a079b32d3d7f87e619b483aeee70b7e26bda393c6028" + - "7c733ecb468fe8b8b11bf809ff76add6b90eb25ad8d3a1052e43ee281e48a3a1ebe7efb5" + - "9e2c4a48765dedeb23f5346242145786cc988c762d230d28dd33bf4c2405d80cbb2cb1d6" + - "4c8f10ba130d50cb174f6ffb9cfc12808297a2cefba385f4fad170f39b51ebd87c12abf9" + - "3c51fc000af90d8aaba78f48923908804a5eb35f617ccf71d201e3708a559e6d16f9f13e" + - "074361eb9007e28d86bb4e0bfa13aad0e9ddd9124e84519de60e2fc6040b18d9fd602b02" + - "684b4c071c3019fc842197d00c120c41654bcbfbc4a096a1c637b79112b81ce1fa3899f9" - -const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + - "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + - "bcbb235d44ccc7dba62e72" - -const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + - "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" + - "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" + - "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" + - "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" + - "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" + - "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" + - "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" + - "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" + - "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" + - "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" + - "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" + - "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" + - "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" + - "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" + - "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" + - "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" + - "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" + - "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" + - "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" + - "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" + - "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" + - "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" + - "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" + - "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" + - "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" + - "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817" - -const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" + - "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" + - "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" + - "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" + - "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" + - "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" + - "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" + - "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" + - "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" + - "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" + - "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" + - "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" + - "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" + - "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" + - "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" + - "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" + - "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" + - "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" + - "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" + - "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" + - "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" + - "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" + - "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" + - "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" + - "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" + - "d68071" - -// Key and certificate for the OCSP responder were not taken from the Thawte -// responder, since CreateResponse requires that we have the private key. -// Instead, they were generated randomly. -const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" + - "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" + - "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" + - "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" + - "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" + - "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" + - "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" + - "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" + - "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" + - "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" + - "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" + - "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" + - "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" + - "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" + - "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" + - "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" + - "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" + - "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" + - "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" + - "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" + - "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" + - "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" + - "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" + - "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" + - "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" + - "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" + - "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" + - "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" + - "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" + - "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" + - "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" + - "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" + - "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" + - "6bdaa059" - -const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + - "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + - "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + - "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + - "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + - "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + - "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + - "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + - "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + - "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + - "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + - "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + - "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + - "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + - "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + - "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + - "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + - "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + - "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + - "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + - "3a25439a94299a65a709756c7a3e568be049d5c38839" - -const errorResponseHex = "30030a0101" diff --git a/crypto/x509/testdata/nist-pkits/README.md b/crypto/x509/testdata/nist-pkits/README.md new file mode 100644 index 00000000000..7b761260d6c --- /dev/null +++ b/crypto/x509/testdata/nist-pkits/README.md @@ -0,0 +1,6 @@ +Test vectors and certificates for the "Path Validation Testing Program" + portion of the NIST Public Key Infrastructure Testing suite: https://csrc.nist.gov/projects/pki-testing. + +Vectors are extracted from the provided PDF: https://csrc.nist.gov/CSRC/media/Projects/PKI-Testing/documents/PKITS.pdf. + +Vectors and test material are public domain (United States Government Work under 17 U.S.C. 105). \ No newline at end of file diff --git a/crypto/x509/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt new file mode 100644 index 00000000000..ae6be6c4c8f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt new file mode 100644 index 00000000000..e36fdb8fc37 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt new file mode 100644 index 00000000000..c296e5a4308 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt new file mode 100644 index 00000000000..7439f85152a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt new file mode 100644 index 00000000000..a6cf3528fa3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt new file mode 100644 index 00000000000..05e4b3ddbe8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt new file mode 100644 index 00000000000..6dfa00d6b8e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BadSignedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BadSignedCACert.crt new file mode 100644 index 00000000000..0a598fcb8eb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BadSignedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt new file mode 100644 index 00000000000..7a7dcec6651 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt new file mode 100644 index 00000000000..33cfbd7ce8c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt new file mode 100644 index 00000000000..4e1245299d4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt new file mode 100644 index 00000000000..7f86064c26b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt new file mode 100644 index 00000000000..1f83cb863f1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt new file mode 100644 index 00000000000..8773e48464c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt new file mode 100644 index 00000000000..b00748cc262 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt new file mode 100644 index 00000000000..963f57a485d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt b/crypto/x509/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt new file mode 100644 index 00000000000..706d98d63b8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DSACACert.crt b/crypto/x509/testdata/nist-pkits/certs/DSACACert.crt new file mode 100644 index 00000000000..14787b05801 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DSACACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt new file mode 100644 index 00000000000..5e2fa5bc921 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt new file mode 100644 index 00000000000..7873bd8d367 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt new file mode 100644 index 00000000000..57f1df4334e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt new file mode 100644 index 00000000000..4967f41d302 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt new file mode 100644 index 00000000000..b6d31236e2c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt new file mode 100644 index 00000000000..4c9c82bbcda Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt new file mode 100644 index 00000000000..6c01f377f46 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt new file mode 100644 index 00000000000..b2e30bd6921 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt b/crypto/x509/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt new file mode 100644 index 00000000000..f4acda66ec5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/GoodCACert.crt b/crypto/x509/testdata/nist-pkits/certs/GoodCACert.crt new file mode 100644 index 00000000000..edbfa648f24 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/GoodCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/GoodsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/GoodsubCACert.crt new file mode 100644 index 00000000000..7a770c31ae7 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/GoodsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt new file mode 100644 index 00000000000..9f4d95f3953 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt new file mode 100644 index 00000000000..e24d88d444d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt new file mode 100644 index 00000000000..4b35bd248ed Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt new file mode 100644 index 00000000000..348df8fe0db Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt new file mode 100644 index 00000000000..3ca79954600 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt new file mode 100644 index 00000000000..6cc192b8ba2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt new file mode 100644 index 00000000000..18033bc34b0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt new file mode 100644 index 00000000000..1f4ad3e1a15 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt new file mode 100644 index 00000000000..a9938aa80e9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt new file mode 100644 index 00000000000..f15d6a9ed22 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt new file mode 100644 index 00000000000..5f7ad1535aa Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt new file mode 100644 index 00000000000..fa59d6fbd0d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt new file mode 100644 index 00000000000..334fed1f111 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt new file mode 100644 index 00000000000..f724473de87 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt new file mode 100644 index 00000000000..468cb7bede2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt new file mode 100644 index 00000000000..806ebf3ce7f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt new file mode 100644 index 00000000000..5f3a49f93e4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt new file mode 100644 index 00000000000..d64ddf53c7a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt new file mode 100644 index 00000000000..fd864ced34c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt new file mode 100644 index 00000000000..455658dbc97 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt new file mode 100644 index 00000000000..63f262b99fb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt new file mode 100644 index 00000000000..a7ef3220436 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt new file mode 100644 index 00000000000..3fd895c9242 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt new file mode 100644 index 00000000000..decbf34aace Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt new file mode 100644 index 00000000000..6ac76654e5e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt new file mode 100644 index 00000000000..48adc0a6d55 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt new file mode 100644 index 00000000000..ed753d42e66 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt new file mode 100644 index 00000000000..a1725b19dac Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt new file mode 100644 index 00000000000..9238109b646 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt new file mode 100644 index 00000000000..af6fdf8c5a9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt new file mode 100644 index 00000000000..3ddef09cabf Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt new file mode 100644 index 00000000000..5cf92f7ce45 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt new file mode 100644 index 00000000000..c4b45f87831 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt new file mode 100644 index 00000000000..56b1ab45831 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt new file mode 100644 index 00000000000..eec4c3c3a6d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt new file mode 100644 index 00000000000..ee6914c15ab Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt new file mode 100644 index 00000000000..30b02759033 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt new file mode 100644 index 00000000000..80ba7a03dd1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt new file mode 100644 index 00000000000..6b7d7de29c6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt new file mode 100644 index 00000000000..ee18fa08fbb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt new file mode 100644 index 00000000000..2c479ca231f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt new file mode 100644 index 00000000000..1ec410d7554 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt new file mode 100644 index 00000000000..053a608d7e6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt new file mode 100644 index 00000000000..1ed661582c4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt new file mode 100644 index 00000000000..a194a040a70 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt new file mode 100644 index 00000000000..c9ad311ac0a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt new file mode 100644 index 00000000000..28ef8f7491e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt new file mode 100644 index 00000000000..0e7f71937a5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt new file mode 100644 index 00000000000..80545971141 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt new file mode 100644 index 00000000000..455cb0240c4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt new file mode 100644 index 00000000000..2e85ce5c21c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt new file mode 100644 index 00000000000..ee48b7fc85e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt new file mode 100644 index 00000000000..e729fe77cda Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt new file mode 100644 index 00000000000..103e0940fe5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt new file mode 100644 index 00000000000..3eaa74deb81 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt new file mode 100644 index 00000000000..1a1da9fe7a0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt new file mode 100644 index 00000000000..2ff84b8b7d3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt new file mode 100644 index 00000000000..d4050e6f4f0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt new file mode 100644 index 00000000000..77b6a3c1472 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt new file mode 100644 index 00000000000..2cbab480b15 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt new file mode 100644 index 00000000000..e703d679051 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt new file mode 100644 index 00000000000..65096685fe2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt new file mode 100644 index 00000000000..e64db473af5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt new file mode 100644 index 00000000000..8630e99cb24 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt new file mode 100644 index 00000000000..42fda8fc122 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt new file mode 100644 index 00000000000..c3f93b5bd7c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt new file mode 100644 index 00000000000..9200cccb39a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt new file mode 100644 index 00000000000..148f9fb23ab Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt new file mode 100644 index 00000000000..3d5b82946bc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt new file mode 100644 index 00000000000..f791140ceda Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt new file mode 100644 index 00000000000..2433e3b95e1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt new file mode 100644 index 00000000000..210bb41fef9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt new file mode 100644 index 00000000000..5509dda847d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt new file mode 100644 index 00000000000..8b9041f5ba4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt new file mode 100644 index 00000000000..32e72a225ec Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt new file mode 100644 index 00000000000..10da3212470 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt new file mode 100644 index 00000000000..d60812c6a41 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt new file mode 100644 index 00000000000..6b3c374331d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt new file mode 100644 index 00000000000..b9594149344 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt new file mode 100644 index 00000000000..ea141b173af Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt new file mode 100644 index 00000000000..de4da9d69b0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt new file mode 100644 index 00000000000..a60b030e9e0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt new file mode 100644 index 00000000000..bbb8271d6bb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt new file mode 100644 index 00000000000..a47f7b20856 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt new file mode 100644 index 00000000000..af3a366dd74 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt new file mode 100644 index 00000000000..3456831e0b9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt new file mode 100644 index 00000000000..828203b11c7 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt new file mode 100644 index 00000000000..2ffd9dd8ce5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt new file mode 100644 index 00000000000..2fc212d33ed Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt new file mode 100644 index 00000000000..9aafebfc25f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt new file mode 100644 index 00000000000..65ca6340ea6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt new file mode 100644 index 00000000000..c8b06f07e40 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt new file mode 100644 index 00000000000..f3526efb69f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt new file mode 100644 index 00000000000..733c152685d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt new file mode 100644 index 00000000000..cfddd3a4359 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt new file mode 100644 index 00000000000..16c103f7446 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt new file mode 100644 index 00000000000..5583f19690c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt new file mode 100644 index 00000000000..f3062e9e480 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt new file mode 100644 index 00000000000..279306ed188 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt new file mode 100644 index 00000000000..f206348963c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt new file mode 100644 index 00000000000..ecf51285fa4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt new file mode 100644 index 00000000000..f536fc6d2bd Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt new file mode 100644 index 00000000000..af5aa4b0d41 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt new file mode 100644 index 00000000000..59722f96227 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt new file mode 100644 index 00000000000..4a0f1916509 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt new file mode 100644 index 00000000000..59a02de9d78 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt new file mode 100644 index 00000000000..447115e6368 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt new file mode 100644 index 00000000000..c28c455abbe Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt new file mode 100644 index 00000000000..dc6d0dda96a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt new file mode 100644 index 00000000000..b8830a24055 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt new file mode 100644 index 00000000000..b96d3c626fd Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt new file mode 100644 index 00000000000..c339f6fae75 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt new file mode 100644 index 00000000000..3e1ba073e13 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt new file mode 100644 index 00000000000..4a7e31caf02 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt new file mode 100644 index 00000000000..e9b7cf2510f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt new file mode 100644 index 00000000000..971d0a5de61 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/LongSerialNumberCACert.crt b/crypto/x509/testdata/nist-pkits/certs/LongSerialNumberCACert.crt new file mode 100644 index 00000000000..12830d90697 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/LongSerialNumberCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/Mapping1to2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/Mapping1to2CACert.crt new file mode 100644 index 00000000000..4b70c9a4fc0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/Mapping1to2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt new file mode 100644 index 00000000000..0a8f1e98114 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt new file mode 100644 index 00000000000..d93d8c79c98 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt b/crypto/x509/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt new file mode 100644 index 00000000000..e6f41a446b3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/NameOrderingCACert.crt b/crypto/x509/testdata/nist-pkits/certs/NameOrderingCACert.crt new file mode 100644 index 00000000000..f1c4a55fbf5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/NameOrderingCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt b/crypto/x509/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt new file mode 100644 index 00000000000..1a4d9ba374c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/NoCRLCACert.crt b/crypto/x509/testdata/nist-pkits/certs/NoCRLCACert.crt new file mode 100644 index 00000000000..71c607dac44 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/NoCRLCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/NoPoliciesCACert.crt b/crypto/x509/testdata/nist-pkits/certs/NoPoliciesCACert.crt new file mode 100644 index 00000000000..3a94cb157d2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/NoPoliciesCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt b/crypto/x509/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt new file mode 100644 index 00000000000..c4f182ad7f9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt b/crypto/x509/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt new file mode 100644 index 00000000000..2666670afb5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt new file mode 100644 index 00000000000..82b5b5e0ee1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt new file mode 100644 index 00000000000..9139bd730d3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt new file mode 100644 index 00000000000..3b9c2a751c4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt new file mode 100644 index 00000000000..91fc36a7273 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt b/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt new file mode 100644 index 00000000000..3500737ab8e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt new file mode 100644 index 00000000000..eb900ebc1cb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt new file mode 100644 index 00000000000..3818b6a7f51 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt new file mode 100644 index 00000000000..db220487cc0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234CACert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234CACert.crt new file mode 100644 index 00000000000..36cf4ce24ea Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt new file mode 100644 index 00000000000..1ab7ab104f6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt new file mode 100644 index 00000000000..df834464bba Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP123CACert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123CACert.crt new file mode 100644 index 00000000000..26262a3d72f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt new file mode 100644 index 00000000000..cef6abeb29c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt new file mode 100644 index 00000000000..49e66b5be01 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt new file mode 100644 index 00000000000..d7b5a42353b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt new file mode 100644 index 00000000000..3a79422477f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP12CACert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12CACert.crt new file mode 100644 index 00000000000..dc1b60de0e8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt new file mode 100644 index 00000000000..081f951b80d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt new file mode 100644 index 00000000000..e8d0bb8ba8d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt new file mode 100644 index 00000000000..c734009d050 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCACert.crt new file mode 100644 index 00000000000..0f3fbbb01a1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP2subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/PoliciesP3CACert.crt b/crypto/x509/testdata/nist-pkits/certs/PoliciesP3CACert.crt new file mode 100644 index 00000000000..9740b309d40 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/PoliciesP3CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt b/crypto/x509/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt new file mode 100644 index 00000000000..9c648a30be0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt b/crypto/x509/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt new file mode 100644 index 00000000000..306303a8465 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/RevokedsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/RevokedsubCACert.crt new file mode 100644 index 00000000000..25705b2f670 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/RevokedsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt b/crypto/x509/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt new file mode 100644 index 00000000000..32ddfe3e315 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt new file mode 100644 index 00000000000..17b3cbba30f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt new file mode 100644 index 00000000000..d747ea1fe51 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt new file mode 100644 index 00000000000..3c1730f41ab Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt new file mode 100644 index 00000000000..e75eb4cd707 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt b/crypto/x509/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt new file mode 100644 index 00000000000..04efaa0659b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/TwoCRLsCACert.crt b/crypto/x509/testdata/nist-pkits/certs/TwoCRLsCACert.crt new file mode 100644 index 00000000000..28eb60a0713 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/TwoCRLsCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UIDCACert.crt b/crypto/x509/testdata/nist-pkits/certs/UIDCACert.crt new file mode 100644 index 00000000000..ec04d744557 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UIDCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt b/crypto/x509/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt new file mode 100644 index 00000000000..2d653ef65b1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt b/crypto/x509/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt new file mode 100644 index 00000000000..ae2ce8a7b49 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt b/crypto/x509/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt new file mode 100644 index 00000000000..69128811ba3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt b/crypto/x509/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt new file mode 100644 index 00000000000..2e2c3ef3d69 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt new file mode 100644 index 00000000000..afb3455e36b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt new file mode 100644 index 00000000000..7d3bcc5d0bc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt new file mode 100644 index 00000000000..5fefe199444 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt new file mode 100644 index 00000000000..1168b580e8c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt new file mode 100644 index 00000000000..3cb86cd1ce6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt new file mode 100644 index 00000000000..c91b9f3665c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt new file mode 100644 index 00000000000..34197f03601 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt new file mode 100644 index 00000000000..9a7919b00ac Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt new file mode 100644 index 00000000000..038e4d7a80a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt new file mode 100644 index 00000000000..69ba3019d4b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt new file mode 100644 index 00000000000..e5235c7ff25 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt new file mode 100644 index 00000000000..8bc3e87b9fc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt new file mode 100644 index 00000000000..2332d4c189a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt new file mode 100644 index 00000000000..f8fe1223249 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt new file mode 100644 index 00000000000..4364e1bcbf5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt new file mode 100644 index 00000000000..3b5ac8be530 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt new file mode 100644 index 00000000000..20fa140e19d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt new file mode 100644 index 00000000000..c59e921bac7 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt new file mode 100644 index 00000000000..c6cfcbb7786 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt new file mode 100644 index 00000000000..f2c4dfc553f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt new file mode 100644 index 00000000000..675711970ce Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt new file mode 100644 index 00000000000..d8b6ce36d0d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt new file mode 100644 index 00000000000..2fc40a6c2f3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt new file mode 100644 index 00000000000..7f77ee81965 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt new file mode 100644 index 00000000000..f97ed0a3e95 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt new file mode 100644 index 00000000000..2ef73e1f697 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt new file mode 100644 index 00000000000..66296ac7e75 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt new file mode 100644 index 00000000000..0a1b85dc680 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt new file mode 100644 index 00000000000..6f69c0c8bca Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt new file mode 100644 index 00000000000..44e890546d5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt new file mode 100644 index 00000000000..96186587225 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt new file mode 100644 index 00000000000..c0a6b3d03ec Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt new file mode 100644 index 00000000000..fc0f65d0796 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt new file mode 100644 index 00000000000..a8ffc872cae Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt new file mode 100644 index 00000000000..7d0b7061137 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt new file mode 100644 index 00000000000..ab39228409f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt new file mode 100644 index 00000000000..89eac753f30 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt new file mode 100644 index 00000000000..865c97542ee Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt new file mode 100644 index 00000000000..eb4306ab5a6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt new file mode 100644 index 00000000000..2d1b18c33f4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt new file mode 100644 index 00000000000..2487d626f7f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt new file mode 100644 index 00000000000..f2bd7d381de Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt new file mode 100644 index 00000000000..e941bbbad00 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt new file mode 100644 index 00000000000..d084fc72158 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt new file mode 100644 index 00000000000..97dd2e72c11 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt new file mode 100644 index 00000000000..ef1ac897e08 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt new file mode 100644 index 00000000000..15825d7eb3b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt new file mode 100644 index 00000000000..60a20316813 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt new file mode 100644 index 00000000000..576a1b81716 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt new file mode 100644 index 00000000000..c0ff7596a09 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt new file mode 100644 index 00000000000..75f67b73c86 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt new file mode 100644 index 00000000000..0a4e150700f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt new file mode 100644 index 00000000000..16968ab59b1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt new file mode 100644 index 00000000000..1516f1ee703 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt new file mode 100644 index 00000000000..a4385c1d959 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt new file mode 100644 index 00000000000..1cb0924ec36 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt new file mode 100644 index 00000000000..ed346760878 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt new file mode 100644 index 00000000000..44e5c1e2532 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt new file mode 100644 index 00000000000..08260919768 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt new file mode 100644 index 00000000000..c42779d70ce Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt new file mode 100644 index 00000000000..be8ef42f19a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt new file mode 100644 index 00000000000..6a24838f5dc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt new file mode 100644 index 00000000000..d1f80a74a4b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt new file mode 100644 index 00000000000..b14d789b5dc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt new file mode 100644 index 00000000000..d55dcb1a6f4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt new file mode 100644 index 00000000000..4059c017a74 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt new file mode 100644 index 00000000000..9145515308c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt new file mode 100644 index 00000000000..b10632b2093 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt new file mode 100644 index 00000000000..593ef98e350 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt new file mode 100644 index 00000000000..2ae810abf9d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt new file mode 100644 index 00000000000..a2eb9a7dc42 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt new file mode 100644 index 00000000000..1a3f7f51427 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt new file mode 100644 index 00000000000..43b44bc5d89 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt new file mode 100644 index 00000000000..8be24581eb9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt new file mode 100644 index 00000000000..b2c832fa41d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt new file mode 100644 index 00000000000..47feb00fd03 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt new file mode 100644 index 00000000000..a93d6663841 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt new file mode 100644 index 00000000000..107f102c98d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt new file mode 100644 index 00000000000..df4ba444504 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt new file mode 100644 index 00000000000..f13524a0dce Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt new file mode 100644 index 00000000000..75daa870284 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt new file mode 100644 index 00000000000..6da79065ea1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt new file mode 100644 index 00000000000..3eec5cc6fe8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt new file mode 100644 index 00000000000..f255d3ad711 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt new file mode 100644 index 00000000000..912968e9502 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt new file mode 100644 index 00000000000..1ad52efdb6c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt new file mode 100644 index 00000000000..76800f5159c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt new file mode 100644 index 00000000000..f3368edd5d1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt new file mode 100644 index 00000000000..8ff0a131e7c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt new file mode 100644 index 00000000000..15b2928401a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt new file mode 100644 index 00000000000..7cf888e16ad Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt new file mode 100644 index 00000000000..23889360cc2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt new file mode 100644 index 00000000000..e93a0e1fe91 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/WrongCRLCACert.crt b/crypto/x509/testdata/nist-pkits/certs/WrongCRLCACert.crt new file mode 100644 index 00000000000..3a96d87cfc5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/WrongCRLCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/anyPolicyCACert.crt b/crypto/x509/testdata/nist-pkits/certs/anyPolicyCACert.crt new file mode 100644 index 00000000000..df54668adbd Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/anyPolicyCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt new file mode 100644 index 00000000000..4b678fee0c5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt new file mode 100644 index 00000000000..d6c7fb805fa Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt new file mode 100644 index 00000000000..27e670ec162 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt new file mode 100644 index 00000000000..6815e4f888f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt new file mode 100644 index 00000000000..2f64a74e135 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt new file mode 100644 index 00000000000..31e6b33a463 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt new file mode 100644 index 00000000000..7cd82a4363c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/distributionPoint1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/distributionPoint1CACert.crt new file mode 100644 index 00000000000..23250812d93 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/distributionPoint1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/distributionPoint2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/distributionPoint2CACert.crt new file mode 100644 index 00000000000..205b62ad165 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/distributionPoint2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt new file mode 100644 index 00000000000..046deefaec8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt new file mode 100644 index 00000000000..de9a0be510e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt new file mode 100644 index 00000000000..03bb3eb2da9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt new file mode 100644 index 00000000000..20e8267eeef Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt new file mode 100644 index 00000000000..f1cb26b375b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt new file mode 100644 index 00000000000..ff1203df3ad Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt new file mode 100644 index 00000000000..c4f9f178746 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt new file mode 100644 index 00000000000..46443aab941 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt new file mode 100644 index 00000000000..cf3611025ed Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt new file mode 100644 index 00000000000..0494c8fe5bb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt new file mode 100644 index 00000000000..6512e9d2e9c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt new file mode 100644 index 00000000000..42e00344afc Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt new file mode 100644 index 00000000000..633536c33ae Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt new file mode 100644 index 00000000000..319e8098786 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt new file mode 100644 index 00000000000..a3c4f2134e9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt new file mode 100644 index 00000000000..3c4512ac28a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt new file mode 100644 index 00000000000..fc9b4232992 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt new file mode 100644 index 00000000000..11ceeb78cc9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt new file mode 100644 index 00000000000..32bbffeb446 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt new file mode 100644 index 00000000000..2c8fd4f6d12 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt new file mode 100644 index 00000000000..16808f7c50a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt new file mode 100644 index 00000000000..846abc924da Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt new file mode 100644 index 00000000000..5baaf35e0f1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt new file mode 100644 index 00000000000..b2f0979ccee Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt new file mode 100644 index 00000000000..4ad9f1e174d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt new file mode 100644 index 00000000000..f514e5d88b7 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt new file mode 100644 index 00000000000..b1e9ff8d068 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt new file mode 100644 index 00000000000..ec47ee63731 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt new file mode 100644 index 00000000000..65155c7b5a0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt new file mode 100644 index 00000000000..ae1891624b9 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt new file mode 100644 index 00000000000..80135df8695 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt new file mode 100644 index 00000000000..3a72ec12fb8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt new file mode 100644 index 00000000000..fd092230fbd Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt new file mode 100644 index 00000000000..93857ab6565 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt new file mode 100644 index 00000000000..134b7f8cb18 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt new file mode 100644 index 00000000000..dfb268d1d33 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt new file mode 100644 index 00000000000..2467c945add Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 00000000000..aa19cec73d2 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt new file mode 100644 index 00000000000..bab8307e330 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt new file mode 100644 index 00000000000..a6d878c8dff Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 00000000000..ef1056f1c39 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt new file mode 100644 index 00000000000..206359f9131 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt new file mode 100644 index 00000000000..452ea547524 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt new file mode 100644 index 00000000000..645f0ae7c4b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt new file mode 100644 index 00000000000..6cfc5926a50 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt new file mode 100644 index 00000000000..840d073f6b5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt new file mode 100644 index 00000000000..c68d496e652 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt new file mode 100644 index 00000000000..87ba14d13a6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt new file mode 100644 index 00000000000..7eed575fb48 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt new file mode 100644 index 00000000000..08f2245ef6c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt new file mode 100644 index 00000000000..3b114631869 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt new file mode 100644 index 00000000000..c190f7a7f24 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt new file mode 100644 index 00000000000..a7ec3bd1ebb Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt new file mode 100644 index 00000000000..c70846206c5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt new file mode 100644 index 00000000000..1be8e993355 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt new file mode 100644 index 00000000000..58308f8939d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt new file mode 100644 index 00000000000..ff6ba166ba4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt new file mode 100644 index 00000000000..5f638c093c0 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt new file mode 100644 index 00000000000..e06b6377a9b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt b/crypto/x509/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt new file mode 100644 index 00000000000..e8d2b7224a8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt b/crypto/x509/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt new file mode 100644 index 00000000000..d75988ad008 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt b/crypto/x509/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt new file mode 100644 index 00000000000..0d0b95030b1 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt new file mode 100644 index 00000000000..ca247b06b40 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt new file mode 100644 index 00000000000..c1cce6e0cec Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt new file mode 100644 index 00000000000..cd65a820e42 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt new file mode 100644 index 00000000000..f205db0a3be Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt new file mode 100644 index 00000000000..ce9b90d2844 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt new file mode 100644 index 00000000000..6e8f97c2035 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt new file mode 100644 index 00000000000..2fc8fb590f8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt new file mode 100644 index 00000000000..b156179e3a7 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt new file mode 100644 index 00000000000..a4242616728 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt new file mode 100644 index 00000000000..87590c3d262 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt new file mode 100644 index 00000000000..f2c43ea8936 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt new file mode 100644 index 00000000000..05a2bac1da8 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt new file mode 100644 index 00000000000..c254a2376d3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt new file mode 100644 index 00000000000..0a8c99dd3e4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt new file mode 100644 index 00000000000..bd686290efe Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt new file mode 100644 index 00000000000..822a383d053 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt new file mode 100644 index 00000000000..e2fd7ae3cd6 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt new file mode 100644 index 00000000000..44c0162e945 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt new file mode 100644 index 00000000000..284f4a9e483 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt new file mode 100644 index 00000000000..9766cf01596 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt new file mode 100644 index 00000000000..e14753174b4 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt b/crypto/x509/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt new file mode 100644 index 00000000000..30aff16129d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt new file mode 100644 index 00000000000..16594b9e970 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt new file mode 100644 index 00000000000..b7a1518eb86 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt new file mode 100644 index 00000000000..db57e9b337f Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt new file mode 100644 index 00000000000..4952094eef3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt new file mode 100644 index 00000000000..3a54e7f2b82 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt new file mode 100644 index 00000000000..650a53f4c2e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt new file mode 100644 index 00000000000..139be532a59 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt new file mode 100644 index 00000000000..a7c216c1640 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt new file mode 100644 index 00000000000..f7ca7ae7e2a Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt new file mode 100644 index 00000000000..9d162690905 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt new file mode 100644 index 00000000000..b53bec1560d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt new file mode 100644 index 00000000000..36fc0d8df48 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt new file mode 100644 index 00000000000..723ae42a47c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt new file mode 100644 index 00000000000..1bd237f766c Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt new file mode 100644 index 00000000000..1a37158581b Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt new file mode 100644 index 00000000000..3047d74341e Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt new file mode 100644 index 00000000000..c6b69ad95d5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt new file mode 100644 index 00000000000..16958532f00 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt new file mode 100644 index 00000000000..093963aeca5 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt new file mode 100644 index 00000000000..58da176c465 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt new file mode 100644 index 00000000000..aba4a7fde45 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt new file mode 100644 index 00000000000..c57e9e4a5bd Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt new file mode 100644 index 00000000000..343efa5ec2d Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt new file mode 100644 index 00000000000..9a8e72a1ce3 Binary files /dev/null and b/crypto/x509/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt differ diff --git a/crypto/x509/testdata/nist-pkits/vectors.json b/crypto/x509/testdata/nist-pkits/vectors.json new file mode 100644 index 00000000000..5842b4326df --- /dev/null +++ b/crypto/x509/testdata/nist-pkits/vectors.json @@ -0,0 +1,5010 @@ +[ + { + "Name": "4.1.1 Valid Signatures Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidCertificatePathTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.1.2 Invalid CA Signature Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BadSignedCACert.crt", + "InvalidCASignatureTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BadSignedCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.1.3 Invalid EE Signature Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "InvalidEESignatureTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.1.4 Valid DSA Signatures Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "DSACACert.crt", + "ValidDSASignaturesTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "DSACACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.1.5 Valid DSA Parameter Inheritance Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "DSACACert.crt", + "DSAParametersInheritedCACert.crt", + "ValidDSAParameterInheritanceTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "DSACACRL.crl", + "DSAParametersInheritedCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.1.6 Invalid DSA Signature Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "DSACACert.crt", + "InvalidDSASignatureTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "DSACACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.1 Invalid CA notBefore Date Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BadnotBeforeDateCACert.crt", + "InvalidCAnotBeforeDateTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BadnotBeforeDateCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.2 Invalid EE notBefore Date Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "InvalidEEnotBeforeDateTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.3 Valid pre2000 UTC notBefore Date Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "Validpre2000UTCnotBeforeDateTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.4 Valid GeneralizedTime notBefore Date Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidGeneralizedTimenotBeforeDateTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.5 Invalid CA notAfter Date Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BadnotAfterDateCACert.crt", + "InvalidCAnotAfterDateTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BadnotAfterDateCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.6 Invalid EE notAfter Date Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "InvalidEEnotAfterDateTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.7 Invalid pre2000 UTC EE notAfter Date Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "Invalidpre2000UTCEEnotAfterDateTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.2.8 Valid GeneralizedTime notAfter Date Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidGeneralizedTimenotAfterDateTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.1 Invalid Name Chaining EE Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "InvalidNameChainingTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.2 Invalid Name Chaining Order Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NameOrderingCACert.crt", + "InvalidNameChainingOrderTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NameOrderCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.3 Valid Name Chaining Whitespace Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidNameChainingWhitespaceTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.4 Valid Name Chaining Whitespace Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidNameChainingWhitespaceTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.5 Valid Name Chaining Capitalization Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidNameChainingCapitalizationTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.6 Valid Name Chaining UIDs Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UIDCACert.crt", + "ValidNameUIDsTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UIDCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.7 Valid RFC3280 Mandatory Attribute Types Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "RFC3280MandatoryAttributeTypesCACert.crt", + "ValidRFC3280MandatoryAttributeTypesTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "RFC3280MandatoryAttributeTypesCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.8 Valid RFC3280 Optional Attribute Types Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "RFC3280OptionalAttributeTypesCACert.crt", + "ValidRFC3280OptionalAttributeTypesTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "RFC3280OptionalAttributeTypesCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.9 Valid UTF8String Encoded Names Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UTF8StringEncodedNamesCACert.crt", + "ValidUTF8StringEncodedNamesTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UTF8StringEncodedNamesCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.10 Valid Rollover from PrintableString to UTF8String Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "RolloverfromPrintableStringtoUTF8StringCACert.crt", + "ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "RolloverfromPrintableStringtoUTF8StringCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.3.11 Valid UTF8String Case Insensitive Match Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UTF8StringCaseInsensitiveMatchCACert.crt", + "ValidUTF8StringCaseInsensitiveMatchTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UTF8StringCaseInsensitiveMatchCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.1 Missing CRL Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NoCRLCACert.crt", + "InvalidMissingCRLTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.2 Invalid Revoked CA Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "RevokedsubCACert.crt", + "InvalidRevokedCATest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "RevokedsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.3 Invalid Revoked EE Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "InvalidRevokedEETest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.4 Invalid Bad CRL Signature Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BadCRLSignatureCACert.crt", + "InvalidBadCRLSignatureTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BadCRLSignatureCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.5 Invalid Bad CRL Issuer Name Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BadCRLIssuerNameCACert.crt", + "InvalidBadCRLIssuerNameTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BadCRLIssuerNameCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.6 Invalid Wrong CRL Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "WrongCRLCACert.crt", + "InvalidWrongCRLTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "WrongCRLCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.7 Valid Two CRLs Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "TwoCRLsCACert.crt", + "ValidTwoCRLsTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "TwoCRLsCAGoodCRL.crl", + "TwoCRLsCABadCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.8 Invalid Unknown CRL Entry Extension Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UnknownCRLEntryExtensionCACert.crt", + "InvalidUnknownCRLEntryExtensionTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UnknownCRLEntryExtensionCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.9 Invalid Unknown CRL Extension Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UnknownCRLExtensionCACert.crt", + "InvalidUnknownCRLExtensionTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UnknownCRLExtensionCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.10 Invalid Unknown CRL Extension Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UnknownCRLExtensionCACert.crt", + "InvalidUnknownCRLExtensionTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "UnknownCRLExtensionCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.11 Invalid Old CRL nextUpdate Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "OldCRLnextUpdateCACert.crt", + "InvalidOldCRLnextUpdateTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "OldCRLnextUpdateCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.12 Invalid pre2000 CRL nextUpdate Test12", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pre2000CRLnextUpdateCACert.crt", + "Invalidpre2000CRLnextUpdateTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pre2000CRLnextUpdateCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.13 Valid GeneralizedTime CRL nextUpdate Test13", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GeneralizedTimeCRLnextUpdateCACert.crt", + "ValidGeneralizedTimeCRLnextUpdateTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GeneralizedTimeCRLnextUpdateCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.14 Valid Negative Serial Number Test14", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NegativeSerialNumberCACert.crt", + "ValidNegativeSerialNumberTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NegativeSerialNumberCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.15 Invalid Negative Serial Number Test15", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NegativeSerialNumberCACert.crt", + "InvalidNegativeSerialNumberTest15EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NegativeSerialNumberCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.16 Valid Long Serial Number Test16", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "LongSerialNumberCACert.crt", + "ValidLongSerialNumberTest16EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "LongSerialNumberCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.17 Valid Long Serial Number Test17", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "LongSerialNumberCACert.crt", + "ValidLongSerialNumberTest17EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "LongSerialNumberCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.18 Invalid Long Serial Number Test18", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "LongSerialNumberCACert.crt", + "InvalidLongSerialNumberTest18EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "LongSerialNumberCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.19 Valid Separate Certificate and CRL Keys Test19", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "SeparateCertificateandCRLKeysCertificateSigningCACert.crt", + "SeparateCertificateandCRLKeysCRLSigningCert.crt", + "ValidSeparateCertificateandCRLKeysTest19EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "SeparateCertificateandCRLKeysCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.20 Invalid Separate Certificate and CRL Keys Test20", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "SeparateCertificateandCRLKeysCertificateSigningCACert.crt", + "SeparateCertificateandCRLKeysCRLSigningCert.crt", + "InvalidSeparateCertificateandCRLKeysTest20EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "SeparateCertificateandCRLKeysCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.4.21 Invalid Separate Certificate and CRL Keys Test21", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt", + "SeparateCertificateandCRLKeysCA2CRLSigningCert.crt", + "InvalidSeparateCertificateandCRLKeysTest21EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "SeparateCertificateandCRLKeysCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.1 Valid Basic Self-Issued Old With New Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedNewKeyCACert.crt", + "BasicSelfIssuedNewKeyOldWithNewCACert.crt", + "ValidBasicSelfIssuedOldWithNewTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedNewKeyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.2 Invalid Basic Self-Issued Old With New Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedNewKeyCACert.crt", + "BasicSelfIssuedNewKeyOldWithNewCACert.crt", + "InvalidBasicSelfIssuedOldWithNewTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedNewKeyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.3 Valid Basic Self-Issued New With Old Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedOldKeyCACert.crt", + "BasicSelfIssuedOldKeyNewWithOldCACert.crt", + "ValidBasicSelfIssuedNewWithOldTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", + "BasicSelfIssuedOldKeyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.4 Valid Basic Self-Issued New With Old Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedOldKeyCACert.crt", + "BasicSelfIssuedOldKeyNewWithOldCACert.crt", + "ValidBasicSelfIssuedNewWithOldTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", + "BasicSelfIssuedOldKeyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.5 Invalid Basic Self-Issued New With Old Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedOldKeyCACert.crt", + "BasicSelfIssuedOldKeyNewWithOldCACert.crt", + "InvalidBasicSelfIssuedNewWithOldTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", + "BasicSelfIssuedOldKeyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.6 Valid Basic Self-Issued CRL Signing Key Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedCRLSigningKeyCACert.crt", + "BasicSelfIssuedCRLSigningKeyCRLCert.crt", + "ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", + "BasicSelfIssuedCRLSigningKeyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.7 Invalid Basic Self-Issued CRL Signing Key Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedCRLSigningKeyCACert.crt", + "BasicSelfIssuedCRLSigningKeyCRLCert.crt", + "InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", + "BasicSelfIssuedCRLSigningKeyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.5.8 Invalid Basic Self-Issued CRL Signing Key Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "BasicSelfIssuedCRLSigningKeyCACert.crt", + "BasicSelfIssuedCRLSigningKeyCRLCert.crt", + "InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", + "BasicSelfIssuedCRLSigningKeyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.1 Invalid Missing basicConstraints Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "MissingbasicConstraintsCACert.crt", + "InvalidMissingbasicConstraintsTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "MissingbasicConstraintsCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.2 Invalid cA False Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "basicConstraintsCriticalcAFalseCACert.crt", + "InvalidcAFalseTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "basicConstraintsCriticalcAFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.3 Invalid cA False Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "basicConstraintsNotCriticalcAFalseCACert.crt", + "InvalidcAFalseTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "basicConstraintsNotCriticalcAFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.4 Valid basicConstraints Not Critical Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "basicConstraintsNotCriticalCACert.crt", + "ValidbasicConstraintsNotCriticalTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "basicConstraintsNotCriticalCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.5 Invalid pathLenConstraint Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "pathLenConstraint0subCACert.crt", + "InvalidpathLenConstraintTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl", + "pathLenConstraint0subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.6 Invalid pathLenConstraint Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "pathLenConstraint0subCACert.crt", + "InvalidpathLenConstraintTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl", + "pathLenConstraint0subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.7 Valid pathLenConstraint Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "ValidpathLenConstraintTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.8 Valid pathLenConstraint Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "ValidpathLenConstraintTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.9 Invalid pathLenConstraint Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA0Cert.crt", + "pathLenConstraint6subsubCA00Cert.crt", + "InvalidpathLenConstraintTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA0CRL.crl", + "pathLenConstraint6subsubCA00CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.10 Invalid pathLenConstraint Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA0Cert.crt", + "pathLenConstraint6subsubCA00Cert.crt", + "InvalidpathLenConstraintTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA0CRL.crl", + "pathLenConstraint6subsubCA00CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.11 Invalid pathLenConstraint Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA1Cert.crt", + "pathLenConstraint6subsubCA11Cert.crt", + "pathLenConstraint6subsubsubCA11XCert.crt", + "InvalidpathLenConstraintTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA1CRL.crl", + "pathLenConstraint6subsubCA11CRL.crl", + "pathLenConstraint6subsubsubCA11XCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.12 Invalid pathLenConstraint Test12", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA1Cert.crt", + "pathLenConstraint6subsubCA11Cert.crt", + "pathLenConstraint6subsubsubCA11XCert.crt", + "InvalidpathLenConstraintTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA1CRL.crl", + "pathLenConstraint6subsubCA11CRL.crl", + "pathLenConstraint6subsubsubCA11XCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.13 Valid pathLenConstraint Test13", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA4Cert.crt", + "pathLenConstraint6subsubCA41Cert.crt", + "pathLenConstraint6subsubsubCA41XCert.crt", + "ValidpathLenConstraintTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA4CRL.crl", + "pathLenConstraint6subsubCA41CRL.crl", + "pathLenConstraint6subsubsubCA41XCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.14 Valid pathLenConstraint Test14", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint6CACert.crt", + "pathLenConstraint6subCA4Cert.crt", + "pathLenConstraint6subsubCA41Cert.crt", + "pathLenConstraint6subsubsubCA41XCert.crt", + "ValidpathLenConstraintTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint6CACRL.crl", + "pathLenConstraint6subCA4CRL.crl", + "pathLenConstraint6subsubCA41CRL.crl", + "pathLenConstraint6subsubsubCA41XCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.15 Valid Self-Issued pathLenConstraint Test15", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "pathLenConstraint0SelfIssuedCACert.crt", + "ValidSelfIssuedpathLenConstraintTest15EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.16 Invalid Self-Issued pathLenConstraint Test16", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint0CACert.crt", + "pathLenConstraint0SelfIssuedCACert.crt", + "pathLenConstraint0subCA2Cert.crt", + "InvalidSelfIssuedpathLenConstraintTest16EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint0CACRL.crl", + "pathLenConstraint0subCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.6.17 Valid Self-Issued pathLenConstraint Test17", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "pathLenConstraint1CACert.crt", + "pathLenConstraint1SelfIssuedCACert.crt", + "pathLenConstraint1subCACert.crt", + "pathLenConstraint1SelfIssuedsubCACert.crt", + "ValidSelfIssuedpathLenConstraintTest17EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "pathLenConstraint1CACRL.crl", + "pathLenConstraint1subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.7.1 Invalid keyUsage Critical keyCertSign False Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "keyUsageCriticalkeyCertSignFalseCACert.crt", + "InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "keyUsageCriticalkeyCertSignFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.7.2 Invalid keyUsage Not Critical keyCertSign False Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "keyUsageNotCriticalkeyCertSignFalseCACert.crt", + "InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "keyUsageNotCriticalkeyCertSignFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.7.3 Valid keyUsage Not Critical Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "keyUsageNotCriticalCACert.crt", + "ValidkeyUsageNotCriticalTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "keyUsageNotCriticalCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.7.4 Invalid keyUsage Critical cRLSign False Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "keyUsageCriticalcRLSignFalseCACert.crt", + "InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "keyUsageCriticalcRLSignFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.7.5 Invalid keyUsage Not Critical cRLSign False Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "keyUsageNotCriticalcRLSignFalseCACert.crt", + "InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "keyUsageNotCriticalcRLSignFalseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.1 All Certificates Same Policy Test1 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidCertificatePathTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.1 All Certificates Same Policy Test1 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidCertificatePathTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.1 All Certificates Same Policy Test1 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidCertificatePathTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.1 All Certificates Same Policy Test1 (Subpart 4)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "ValidCertificatePathTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1", + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.2 All Certificates No Policies Test2 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NoPoliciesCACert.crt", + "AllCertificatesNoPoliciesTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NoPoliciesCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.2 All Certificates No Policies Test2 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NoPoliciesCACert.crt", + "AllCertificatesNoPoliciesTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NoPoliciesCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.3 Different Policies Test3 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "PoliciesP2subCACert.crt", + "DifferentPoliciesTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "PoliciesP2subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.3 Different Policies Test3 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "PoliciesP2subCACert.crt", + "DifferentPoliciesTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "PoliciesP2subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.3 Different Policies Test3 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "PoliciesP2subCACert.crt", + "DifferentPoliciesTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "PoliciesP2subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-1", + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.4 Different Policies Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "GoodsubCACert.crt", + "DifferentPoliciesTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "GoodsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.5 Different Policies Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "PoliciesP2subCA2Cert.crt", + "DifferentPoliciesTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "PoliciesP2subCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.6 Overlapping Policies Test6 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP1234CACert.crt", + "PoliciesP1234subCAP123Cert.crt", + "PoliciesP1234subsubCAP123P12Cert.crt", + "OverlappingPoliciesTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP1234CACRL.crl", + "PoliciesP1234subCAP123CRL.crl", + "PoliciesP1234subsubCAP123P12CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.6 Overlapping Policies Test6 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP1234CACert.crt", + "PoliciesP1234subCAP123Cert.crt", + "PoliciesP1234subsubCAP123P12Cert.crt", + "OverlappingPoliciesTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP1234CACRL.crl", + "PoliciesP1234subCAP123CRL.crl", + "PoliciesP1234subsubCAP123P12CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.6 Overlapping Policies Test6 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP1234CACert.crt", + "PoliciesP1234subCAP123Cert.crt", + "PoliciesP1234subsubCAP123P12Cert.crt", + "OverlappingPoliciesTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP1234CACRL.crl", + "PoliciesP1234subCAP123CRL.crl", + "PoliciesP1234subsubCAP123P12CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.7 Different Policies Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP123CACert.crt", + "PoliciesP123subCAP12Cert.crt", + "PoliciesP123subsubCAP12P1Cert.crt", + "DifferentPoliciesTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP123CACRL.crl", + "PoliciesP123subCAP12CRL.crl", + "PoliciesP123subsubCAP12P1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.8 Different Policies Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "PoliciesP12subCAP1Cert.crt", + "PoliciesP12subsubCAP1P2Cert.crt", + "DifferentPoliciesTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl", + "PoliciesP12subCAP1CRL.crl", + "PoliciesP12subsubCAP1P2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.9 Different Policies Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP123CACert.crt", + "PoliciesP123subCAP12Cert.crt", + "PoliciesP123subsubCAP12P2Cert.crt", + "PoliciesP123subsubsubCAP12P2P1Cert.crt", + "DifferentPoliciesTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP123CACRL.crl", + "PoliciesP123subCAP12CRL.crl", + "PoliciesP123subsubCAP2P2CRL.crl", + "PoliciesP123subsubsubCAP12P2P1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.10 All Certificates Same Policies Test10 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "AllCertificatesSamePoliciesTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.10 All Certificates Same Policies Test10 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "AllCertificatesSamePoliciesTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.10 All Certificates Same Policies Test10 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "AllCertificatesSamePoliciesTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.11 All Certificates AnyPolicy Test11 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "anyPolicyCACert.crt", + "AllCertificatesanyPolicyTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "anyPolicyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.11 All Certificates AnyPolicy Test11 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "anyPolicyCACert.crt", + "AllCertificatesanyPolicyTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "anyPolicyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.12 Different Policies Test12", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP3CACert.crt", + "DifferentPoliciesTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP3CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.13 All Certificates Same Policies Test13 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP123CACert.crt", + "AllCertificatesSamePoliciesTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP123CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.13 All Certificates Same Policies Test13 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP123CACert.crt", + "AllCertificatesSamePoliciesTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP123CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.13 All Certificates Same Policies Test13 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP123CACert.crt", + "AllCertificatesSamePoliciesTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP123CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-3" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.14 AnyPolicy Test14 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "anyPolicyCACert.crt", + "AnyPolicyTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "anyPolicyCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.14 AnyPolicy Test14 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "anyPolicyCACert.crt", + "AnyPolicyTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "anyPolicyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.15 User Notice Qualifier Test15", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UserNoticeQualifierTest15EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.16 User Notice Qualifier Test16", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "UserNoticeQualifierTest16EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.17 User Notice Qualifier Test17", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "UserNoticeQualifierTest17EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.18 User Notice Qualifier Test18 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "UserNoticeQualifierTest18EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.18 User Notice Qualifier Test18 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PoliciesP12CACert.crt", + "UserNoticeQualifierTest18EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PoliciesP12CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.19 User Notice Qualifier Test19", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "UserNoticeQualifierTest19EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.8.20 CPS Pointer Qualifier Test20", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "CPSPointerQualifierTest20EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": true, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.1 Valid RequireExplicitPolicy Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy10CACert.crt", + "requireExplicitPolicy10subCACert.crt", + "requireExplicitPolicy10subsubCACert.crt", + "requireExplicitPolicy10subsubsubCACert.crt", + "ValidrequireExplicitPolicyTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy10CACRL.crl", + "requireExplicitPolicy10subCACRL.crl", + "requireExplicitPolicy10subsubCACRL.crl", + "requireExplicitPolicy10subsubsubCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.2 Valid RequireExplicitPolicy Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy5CACert.crt", + "requireExplicitPolicy5subCACert.crt", + "requireExplicitPolicy5subsubCACert.crt", + "requireExplicitPolicy5subsubsubCACert.crt", + "ValidrequireExplicitPolicyTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy5CACRL.crl", + "requireExplicitPolicy5subCACRL.crl", + "requireExplicitPolicy5subsubCACRL.crl", + "requireExplicitPolicy5subsubsubCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.3 Invalid RequireExplicitPolicy Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy4CACert.crt", + "requireExplicitPolicy4subCACert.crt", + "requireExplicitPolicy4subsubCACert.crt", + "requireExplicitPolicy4subsubsubCACert.crt", + "InvalidrequireExplicitPolicyTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy4CACRL.crl", + "requireExplicitPolicy4subCACRL.crl", + "requireExplicitPolicy4subsubCACRL.crl", + "requireExplicitPolicy4subsubsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.4 Valid RequireExplicitPolicy Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy0CACert.crt", + "requireExplicitPolicy0subCACert.crt", + "requireExplicitPolicy0subsubCACert.crt", + "requireExplicitPolicy0subsubsubCACert.crt", + "ValidrequireExplicitPolicyTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy0CACRL.crl", + "requireExplicitPolicy0subCACRL.crl", + "requireExplicitPolicy0subsubCACRL.crl", + "requireExplicitPolicy0subsubsubCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.5 Invalid RequireExplicitPolicy Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy7CACert.crt", + "requireExplicitPolicy7subCARE2Cert.crt", + "requireExplicitPolicy7subsubCARE2RE4Cert.crt", + "requireExplicitPolicy7subsubsubCARE2RE4Cert.crt", + "InvalidrequireExplicitPolicyTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy7CACRL.crl", + "requireExplicitPolicy7subCARE2CRL.crl", + "requireExplicitPolicy7subsubCARE2RE4CRL.crl", + "requireExplicitPolicy7subsubsubCARE2RE4CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.6 Valid Self-Issued requireExplicitPolicy Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy2CACert.crt", + "requireExplicitPolicy2SelfIssuedCACert.crt", + "ValidSelfIssuedrequireExplicitPolicyTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.7 Invalid Self-Issued requireExplicitPolicy Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy2CACert.crt", + "requireExplicitPolicy2SelfIssuedCACert.crt", + "requireExplicitPolicy2subCACert.crt", + "InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy2CACRL.crl", + "requireExplicitPolicy2subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.9.8 Invalid Self-Issued requireExplicitPolicy Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "requireExplicitPolicy2CACert.crt", + "requireExplicitPolicy2SelfIssuedCACert.crt", + "requireExplicitPolicy2subCACert.crt", + "requireExplicitPolicy2SelfIssuedsubCACert.crt", + "InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "requireExplicitPolicy2CACRL.crl", + "requireExplicitPolicy2subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.1.1 Valid Policy Mapping Test1 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "Mapping1to2CACert.crt", + "ValidPolicyMappingTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "Mapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.1.2 Valid Policy Mapping Test1 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "Mapping1to2CACert.crt", + "ValidPolicyMappingTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "Mapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.1.3 Valid Policy Mapping Test1 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "Mapping1to2CACert.crt", + "ValidPolicyMappingTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "Mapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": true, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.2 Invalid Policy Mapping Test2 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "Mapping1to2CACert.crt", + "InvalidPolicyMappingTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "Mapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.2 Invalid Policy Mapping Test2 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "Mapping1to2CACert.crt", + "InvalidPolicyMappingTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "Mapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": true, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.3 Valid Policy Mapping Test3 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P12Mapping1to3CACert.crt", + "P12Mapping1to3subCACert.crt", + "P12Mapping1to3subsubCACert.crt", + "ValidPolicyMappingTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P12Mapping1to3CACRL.crl", + "P12Mapping1to3subCACRL.crl", + "P12Mapping1to3subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.3 Valid Policy Mapping Test3 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P12Mapping1to3CACert.crt", + "P12Mapping1to3subCACert.crt", + "P12Mapping1to3subsubCACert.crt", + "ValidPolicyMappingTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P12Mapping1to3CACRL.crl", + "P12Mapping1to3subCACRL.crl", + "P12Mapping1to3subsubCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.4 Invalid Policy Mapping Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P12Mapping1to3CACert.crt", + "P12Mapping1to3subCACert.crt", + "P12Mapping1to3subsubCACert.crt", + "InvalidPolicyMappingTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P12Mapping1to3CACRL.crl", + "P12Mapping1to3subCACRL.crl", + "P12Mapping1to3subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.5 Valid Policy Mapping Test5 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1Mapping1to234CACert.crt", + "P1Mapping1to234subCACert.crt", + "ValidPolicyMappingTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1Mapping1to234CACRL.crl", + "P1Mapping1to234subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.5 Valid Policy Mapping Test5 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1Mapping1to234CACert.crt", + "P1Mapping1to234subCACert.crt", + "ValidPolicyMappingTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1Mapping1to234CACRL.crl", + "P1Mapping1to234subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-6" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.6 Valid Policy Mapping Test6 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1Mapping1to234CACert.crt", + "P1Mapping1to234subCACert.crt", + "ValidPolicyMappingTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1Mapping1to234CACRL.crl", + "P1Mapping1to234subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.6 Valid Policy Mapping Test6 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1Mapping1to234CACert.crt", + "P1Mapping1to234subCACert.crt", + "ValidPolicyMappingTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1Mapping1to234CACRL.crl", + "P1Mapping1to234subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-6" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.7 Invalid Mapping From anyPolicy Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "MappingFromanyPolicyCACert.crt", + "InvalidMappingFromanyPolicyTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "MappingFromanyPolicyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.8 Invalid Mapping To anyPolicy Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "MappingToanyPolicyCACert.crt", + "InvalidMappingToanyPolicyTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "MappingToanyPolicyCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.9 Valid Policy Mapping Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "PanyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "PanyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.10 Invalid Policy Mapping Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "GoodsubCAPanyPolicyMapping1to2CACert.crt", + "InvalidPolicyMappingTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "GoodsubCAPanyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.11 Valid Policy Mapping Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "GoodCACert.crt", + "GoodsubCAPanyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl", + "GoodsubCAPanyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.12 Valid Policy Mapping Test12 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P12Mapping1to3CACert.crt", + "ValidPolicyMappingTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P12Mapping1to3CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.12 Valid Policy Mapping Test12 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P12Mapping1to3CACert.crt", + "ValidPolicyMappingTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P12Mapping1to3CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.13 Valid Policy Mapping Test13 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1anyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1anyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.13 Valid Policy Mapping Test13 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1anyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1anyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "NIST-test-policy-1", + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.13 Valid Policy Mapping Test13 (Subpart 3)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1anyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1anyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "NIST-test-policy-2" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.10.14 Valid Policy Mapping Test14", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "P1anyPolicyMapping1to2CACert.crt", + "ValidPolicyMappingTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "P1anyPolicyMapping1to2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.1 Invalid inhibitPolicyMapping Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping0CACert.crt", + "inhibitPolicyMapping0subCACert.crt", + "InvalidinhibitPolicyMappingTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping0CACRL.crl", + "inhibitPolicyMapping0subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.2 Valid inhibitPolicyMapping Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P12CACert.crt", + "inhibitPolicyMapping1P12subCACert.crt", + "ValidinhibitPolicyMappingTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P12CACRL.crl", + "inhibitPolicyMapping1P12subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.3 Invalid inhibitPolicyMapping Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P12CACert.crt", + "inhibitPolicyMapping1P12subCACert.crt", + "inhibitPolicyMapping1P12subsubCACert.crt", + "InvalidinhibitPolicyMappingTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P12CACRL.crl", + "inhibitPolicyMapping1P12subCACRL.crl", + "inhibitPolicyMapping1P12subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.4 Valid inhibitPolicyMapping Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P12CACert.crt", + "inhibitPolicyMapping1P12subCACert.crt", + "inhibitPolicyMapping1P12subsubCACert.crt", + "ValidinhibitPolicyMappingTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P12CACRL.crl", + "inhibitPolicyMapping1P12subCACRL.crl", + "inhibitPolicyMapping1P12subsubCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.5 Invalid inhibitPolicyMapping Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping5CACert.crt", + "inhibitPolicyMapping5subCACert.crt", + "inhibitPolicyMapping5subsubCACert.crt", + "inhibitPolicyMapping5subsubsubCACert.crt", + "InvalidinhibitPolicyMappingTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping5CACRL.crl", + "inhibitPolicyMapping5subCACRL.crl", + "inhibitPolicyMapping5subsubCACRL.crl", + "inhibitPolicyMapping5subsubsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.6 Invalid inhibitPolicyMapping Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P12CACert.crt", + "inhibitPolicyMapping1P12subCAIPM5Cert.crt", + "inhibitPolicyMapping1P12subsubCAIPM5Cert.crt", + "InvalidinhibitPolicyMappingTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P12CACRL.crl", + "inhibitPolicyMapping1P12subCAIPM5CRL.crl", + "inhibitPolicyMapping1P12subsubCAIPM5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.7 Valid Self-Issued inhibitPolicyMapping Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P1CACert.crt", + "inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "inhibitPolicyMapping1P1subCACert.crt", + "ValidSelfIssuedinhibitPolicyMappingTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P1CACRL.crl", + "inhibitPolicyMapping1P1subCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.8 Invalid Self-Issued inhibitPolicyMapping Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P1CACert.crt", + "inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "inhibitPolicyMapping1P1subCACert.crt", + "inhibitPolicyMapping1P1subsubCACert.crt", + "InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P1CACRL.crl", + "inhibitPolicyMapping1P1subCACRL.crl", + "inhibitPolicyMapping1P1subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.9 Invalid Self-Issued inhibitPolicyMapping Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P1CACert.crt", + "inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "inhibitPolicyMapping1P1subCACert.crt", + "inhibitPolicyMapping1P1subsubCACert.crt", + "InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P1CACRL.crl", + "inhibitPolicyMapping1P1subCACRL.crl", + "inhibitPolicyMapping1P1subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.10 Invalid Self-Issued inhibitPolicyMapping Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P1CACert.crt", + "inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "inhibitPolicyMapping1P1subCACert.crt", + "inhibitPolicyMapping1P1SelfIssuedsubCACert.crt", + "InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P1CACRL.crl", + "inhibitPolicyMapping1P1subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.11.11 Invalid Self-Issued inhibitPolicyMapping Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitPolicyMapping1P1CACert.crt", + "inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "inhibitPolicyMapping1P1subCACert.crt", + "inhibitPolicyMapping1P1SelfIssuedsubCACert.crt", + "InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitPolicyMapping1P1CACRL.crl", + "inhibitPolicyMapping1P1subCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.1 Invalid inhibitAnyPolicy Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy0CACert.crt", + "InvalidinhibitAnyPolicyTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy0CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.2 Valid inhibitAnyPolicy Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy0CACert.crt", + "ValidinhibitAnyPolicyTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy0CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.3 inhibitAnyPolicy Test3 (Subpart 1)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1subCA1Cert.crt", + "inhibitAnyPolicyTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA1CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.3 inhibitAnyPolicy Test3 (Subpart 2)", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1subCA1Cert.crt", + "inhibitAnyPolicyTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": true + }, + { + "Name": "4.12.4 Invalid inhibitAnyPolicy Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1subCA1Cert.crt", + "InvalidinhibitAnyPolicyTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.5 Invalid inhibitAnyPolicy Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy5CACert.crt", + "inhibitAnyPolicy5subCACert.crt", + "inhibitAnyPolicy5subsubCACert.crt", + "InvalidinhibitAnyPolicyTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy5CACRL.crl", + "inhibitAnyPolicy5subCACRL.crl", + "inhibitAnyPolicy5subsubCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.6 Invalid inhibitAnyPolicy Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1subCAIAP5Cert.crt", + "InvalidinhibitAnyPolicyTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCAIAP5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.7 Valid Self-Issued inhibitAnyPolicy Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1SelfIssuedCACert.crt", + "inhibitAnyPolicy1subCA2Cert.crt", + "ValidSelfIssuedinhibitAnyPolicyTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA2CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.8 Invalid Self-Issued inhibitAnyPolicy Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1SelfIssuedCACert.crt", + "inhibitAnyPolicy1subCA2Cert.crt", + "inhibitAnyPolicy1subsubCA2Cert.crt", + "InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA2CRL.crl", + "inhibitAnyPolicy1subsubCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.9 Valid Self-Issued inhibitAnyPolicy Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1SelfIssuedCACert.crt", + "inhibitAnyPolicy1subCA2Cert.crt", + "inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt", + "ValidSelfIssuedinhibitAnyPolicyTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA2CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.12.10 Invalid Self-Issued inhibitAnyPolicy Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "inhibitAnyPolicy1CACert.crt", + "inhibitAnyPolicy1SelfIssuedCACert.crt", + "inhibitAnyPolicy1subCA2Cert.crt", + "InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "inhibitAnyPolicy1CACRL.crl", + "inhibitAnyPolicy1subCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.1 Valid DN nameConstraints Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "ValidDNnameConstraintsTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.2 Invalid DN nameConstraints Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "InvalidDNnameConstraintsTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.3 Invalid DN nameConstraints Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "InvalidDNnameConstraintsTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.4 Valid DN nameConstraints Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "ValidDNnameConstraintsTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.5 Valid DN nameConstraints Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN2CACert.crt", + "ValidDNnameConstraintsTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.6 Valid DN nameConstraints Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "ValidDNnameConstraintsTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.7 Invalid DN nameConstraints Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "InvalidDNnameConstraintsTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.8 Invalid DN nameConstraints Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN4CACert.crt", + "InvalidDNnameConstraintsTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN4CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.9 Invalid DN nameConstraints Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN4CACert.crt", + "InvalidDNnameConstraintsTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN4CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.10 Invalid DN nameConstraints Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN5CACert.crt", + "InvalidDNnameConstraintsTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN5CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.11 Valid DN nameConstraints Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN5CACert.crt", + "ValidDNnameConstraintsTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN5CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.12 Invalid DN nameConstraints Test12", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA1Cert.crt", + "InvalidDNnameConstraintsTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.13 Invalid DN nameConstraints Test13", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA2Cert.crt", + "InvalidDNnameConstraintsTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.14 Valid DN nameConstraints Test14", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA2Cert.crt", + "ValidDNnameConstraintsTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA2CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.15 Invalid DN nameConstraints Test15", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "nameConstraintsDN3subCA1Cert.crt", + "InvalidDNnameConstraintsTest15EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl", + "nameConstraintsDN3subCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.16 Invalid DN nameConstraints Test16", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "nameConstraintsDN3subCA1Cert.crt", + "InvalidDNnameConstraintsTest16EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl", + "nameConstraintsDN3subCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.17 Invalid DN nameConstraints Test17", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "nameConstraintsDN3subCA2Cert.crt", + "InvalidDNnameConstraintsTest17EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl", + "nameConstraintsDN3subCA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.18 Valid DN nameConstraints Test18", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN3CACert.crt", + "nameConstraintsDN3subCA2Cert.crt", + "ValidDNnameConstraintsTest18EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN3CACRL.crl", + "nameConstraintsDN3subCA2CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.19 Valid Self-Issued DN nameConstraints Test19", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1SelfIssuedCACert.crt", + "ValidDNnameConstraintsTest19EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.20 Invalid Self-Issued DN nameConstraints Test20", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "InvalidDNnameConstraintsTest20EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.21 Valid RFC822 nameConstraints Test21", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA1Cert.crt", + "ValidRFC822nameConstraintsTest21EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA1CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.22 Invalid RFC822 nameConstraints Test22", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA1Cert.crt", + "InvalidRFC822nameConstraintsTest22EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.23 Valid RFC822 nameConstraints Test23", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA2Cert.crt", + "ValidRFC822nameConstraintsTest23EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA2CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.24 Invalid RFC822 nameConstraints Test24", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA2Cert.crt", + "InvalidRFC822nameConstraintsTest24EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA2CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.25 Valid RFC822 nameConstraints Test25", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA3Cert.crt", + "ValidRFC822nameConstraintsTest25EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA3CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.26 Invalid RFC822 nameConstraints Test26", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsRFC822CA3Cert.crt", + "InvalidRFC822nameConstraintsTest26EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsRFC822CA3CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.27 Valid DN and RFC822 nameConstraints Test27", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA3Cert.crt", + "ValidDNandRFC822nameConstraintsTest27EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA3CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.28 Invalid DN and RFC822 nameConstraints Test28", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA3Cert.crt", + "InvalidDNandRFC822nameConstraintsTest28EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA3CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.29 Invalid DN and RFC822 nameConstraints Test29", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDN1CACert.crt", + "nameConstraintsDN1subCA3Cert.crt", + "InvalidDNandRFC822nameConstraintsTest29EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDN1CACRL.crl", + "nameConstraintsDN1subCA3CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.30 Valid DNS nameConstraints Test30", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDNS1CACert.crt", + "ValidDNSnameConstraintsTest30EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDNS1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.31 Invalid DNS nameConstraints Test31", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDNS1CACert.crt", + "InvalidDNSnameConstraintsTest31EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDNS1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.32 Valid DNS nameConstraints Test32", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDNS2CACert.crt", + "ValidDNSnameConstraintsTest32EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDNS2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.33 Invalid DNS nameConstraints Test33", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDNS2CACert.crt", + "InvalidDNSnameConstraintsTest33EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDNS2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.34 Valid URI nameConstraints Test34", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsURI1CACert.crt", + "ValidURInameConstraintsTest34EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsURI1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.35 Invalid URI nameConstraints Test35", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsURI1CACert.crt", + "InvalidURInameConstraintsTest35EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsURI1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.36 Valid URI nameConstraints Test36", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsURI2CACert.crt", + "ValidURInameConstraintsTest36EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsURI2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.37 Invalid URI nameConstraints Test37", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsURI2CACert.crt", + "InvalidURInameConstraintsTest37EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsURI2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.13.38 Invalid DNS nameConstraints Test38", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "nameConstraintsDNS1CACert.crt", + "InvalidDNSnameConstraintsTest38EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "nameConstraintsDNS1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.1 Valid distributionPoint Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint1CACert.crt", + "ValiddistributionPointTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.2 Invalid distributionPoint Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint1CACert.crt", + "InvaliddistributionPointTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.3 Invalid distributionPoint Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint1CACert.crt", + "InvaliddistributionPointTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint1CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.4 Valid distributionPoint Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint1CACert.crt", + "ValiddistributionPointTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint1CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.5 Valid distributionPoint Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint2CACert.crt", + "ValiddistributionPointTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.6 Invalid distributionPoint Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint2CACert.crt", + "InvaliddistributionPointTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.7 Valid distributionPoint Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint2CACert.crt", + "ValiddistributionPointTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint2CACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.8 Invalid distributionPoint Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint2CACert.crt", + "InvaliddistributionPointTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.9 Invalid distributionPoint Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "distributionPoint2CACert.crt", + "InvaliddistributionPointTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "distributionPoint2CACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.10 Valid No issuingDistributionPoint Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "NoissuingDistributionPointCACert.crt", + "ValidNoissuingDistributionPointTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "NoissuingDistributionPointCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.11 Invalid onlyContainsUserCerts CRL Test11", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlyContainsUserCertsCACert.crt", + "InvalidonlyContainsUserCertsTest11EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlyContainsUserCertsCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.12 Invalid onlyContainsCACerts CRL Test12", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlyContainsCACertsCACert.crt", + "InvalidonlyContainsCACertsTest12EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlyContainsCACertsCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.13 Valid onlyContainsCACerts CRL Test13", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlyContainsCACertsCACert.crt", + "ValidonlyContainsCACertsTest13EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlyContainsCACertsCACRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.14 Invalid onlyContainsAttributeCerts Test14", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlyContainsAttributeCertsCACert.crt", + "InvalidonlyContainsAttributeCertsTest14EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlyContainsAttributeCertsCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.15 Invalid onlySomeReasons Test15", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA1Cert.crt", + "InvalidonlySomeReasonsTest15EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA1compromiseCRL.crl", + "onlySomeReasonsCA1otherreasonsCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.16 Invalid onlySomeReasons Test16", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA1Cert.crt", + "InvalidonlySomeReasonsTest16EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA1compromiseCRL.crl", + "onlySomeReasonsCA1otherreasonsCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.17 Invalid onlySomeReasons Test17", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA2Cert.crt", + "InvalidonlySomeReasonsTest17EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA2CRL1.crl", + "onlySomeReasonsCA2CRL2.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.18 Valid onlySomeReasons Test18", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA3Cert.crt", + "ValidonlySomeReasonsTest18EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA3compromiseCRL.crl", + "onlySomeReasonsCA3otherreasonsCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.19 Valid onlySomeReasons Test19", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA4Cert.crt", + "ValidonlySomeReasonsTest19EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA4compromiseCRL.crl", + "onlySomeReasonsCA4otherreasonsCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.20 Invalid onlySomeReasons Test20", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA4Cert.crt", + "InvalidonlySomeReasonsTest20EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA4compromiseCRL.crl", + "onlySomeReasonsCA4otherreasonsCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.21 Invalid onlySomeReasons Test21", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "onlySomeReasonsCA4Cert.crt", + "InvalidonlySomeReasonsTest21EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "onlySomeReasonsCA4compromiseCRL.crl", + "onlySomeReasonsCA4otherreasonsCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.22 Valid IDP with indirectCRL Test22", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA1Cert.crt", + "ValidIDPwithindirectCRLTest22EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA1CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.23 Invalid IDP with indirectCRL Test23", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA1Cert.crt", + "InvalidIDPwithindirectCRLTest23EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.24 Valid IDP with indirectCRL Test24", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA2Cert.crt", + "indirectCRLCA1Cert.crt", + "ValidIDPwithindirectCRLTest24EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA1CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.25 Valid IDP with indirectCRL Test25", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA2Cert.crt", + "indirectCRLCA1Cert.crt", + "ValidIDPwithindirectCRLTest25EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA1CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.26 Invalid IDP with indirectCRL Test26", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA2Cert.crt", + "indirectCRLCA1Cert.crt", + "InvalidIDPwithindirectCRLTest26EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA1CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.27 Invalid cRLIssuer Test27", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA2Cert.crt", + "GoodCACert.crt", + "InvalidcRLIssuerTest27EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "GoodCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.28 Valid cRLIssuer Test28", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA3Cert.crt", + "indirectCRLCA3cRLIssuerCert.crt", + "ValidcRLIssuerTest28EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA3CRL.crl", + "indirectCRLCA3cRLIssuerCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.29 Valid cRLIssuer Test29", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA3Cert.crt", + "indirectCRLCA3cRLIssuerCert.crt", + "ValidcRLIssuerTest29EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA3CRL.crl", + "indirectCRLCA3cRLIssuerCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.30 Valid cRLIssuer Test30", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA4Cert.crt", + "indirectCRLCA4cRLIssuerCert.crt", + "ValidcRLIssuerTest30EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA4cRLIssuerCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.31 Invalid cRLIssuer Test31", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA5Cert.crt", + "indirectCRLCA6Cert.crt", + "InvalidcRLIssuerTest31EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.32 Invalid cRLIssuer Test32", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA5Cert.crt", + "indirectCRLCA6Cert.crt", + "InvalidcRLIssuerTest32EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.33 Valid cRLIssuer Test33", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA5Cert.crt", + "indirectCRLCA6Cert.crt", + "ValidcRLIssuerTest33EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA5CRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.34 Invalid cRLIssuer Test34", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA5Cert.crt", + "InvalidcRLIssuerTest34EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.14.35 Invalid cRLIssuer Test35", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "indirectCRLCA5Cert.crt", + "InvalidcRLIssuerTest35EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "indirectCRLCA5CRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.1 Invalid deltaCRLIndicator No Base Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLIndicatorNoBaseCACert.crt", + "InvaliddeltaCRLIndicatorNoBaseTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLIndicatorNoBaseCACRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.2 Valid delta-CRL Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "ValiddeltaCRLTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.3 Invalid delta-CRL Test3", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "InvaliddeltaCRLTest3EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.4 Invalid delta-CRL Test4", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "InvaliddeltaCRLTest4EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.5 Valid delta-CRL Test5", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "ValiddeltaCRLTest5EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.6 Invalid delta-CRL Test6", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "InvaliddeltaCRLTest6EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.7 Valid delta-CRL Test7", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA1Cert.crt", + "ValiddeltaCRLTest7EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA1CRL.crl", + "deltaCRLCA1deltaCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.8 Valid delta-CRL Test8", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA2Cert.crt", + "ValiddeltaCRLTest8EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA2CRL.crl", + "deltaCRLCA2deltaCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.9 Invalid delta-CRL Test9", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA2Cert.crt", + "InvaliddeltaCRLTest9EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA2CRL.crl", + "deltaCRLCA2deltaCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.15.10 Invalid delta-CRL Test10", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "deltaCRLCA3Cert.crt", + "InvaliddeltaCRLTest10EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl", + "deltaCRLCA3CRL.crl", + "deltaCRLCA3deltaCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.16.1 Valid Unknown Not Critical Certificate Extension Test1", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "ValidUnknownNotCriticalCertificateExtensionTest1EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl" + ], + "ShouldValidate": true, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + }, + { + "Name": "4.16.2 Invalid Unknown Critical Certificate Extension Test2", + "CertPath": [ + "TrustAnchorRootCertificate.crt", + "InvalidUnknownCriticalCertificateExtensionTest2EE.crt" + ], + "CRLPath": [ + "TrustAnchorRootCRL.crl" + ], + "ShouldValidate": false, + "InitialPolicySet": [ + "anyPolicy" + ], + "InitialPolicyMappingInhibit": false, + "InitialExplicitPolicy": false, + "InitialAnyPolicyInhibit": false + } +] \ No newline at end of file diff --git a/crypto/x509/testdata/policy_intermediate.pem b/crypto/x509/testdata/policy_intermediate.pem new file mode 100644 index 00000000000..759deb4c43a --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgYUwgYIwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAoGCCqGSM49BAMCA0cAMEQCIFN2ZtknXQ9vz23qD1ecprC9iIo7 +j/SI42Ub64qZQaraAiA+CRCWJz/l+NQ1+TPWYDDWY6Wh2L9Wbddh1Nj5KJEkhQ== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_any.pem b/crypto/x509/testdata/policy_intermediate_any.pem new file mode 100644 index 00000000000..0931964f520 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_any.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjajBoMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjARBgNVHSAECjAIMAYGBFUdIAAwCgYIKoZIzj0EAwIDSQAwRgIh +AJbyXshUwjsFCiqrJkg91GzJdhZZ+3WXOekCJgi8uEESAiEAhv4sEE0wRRqgHDjl +vIt26IELfFE2Z/FBF3ihGmi6NoI= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_duplicate.pem b/crypto/x509/testdata/policy_intermediate_duplicate.pem new file mode 100644 index 00000000000..0eafe8d86a8 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBvDCCAWKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZYwgZMwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMDwGA1UdIAQ1MDMwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMA8GDSqGSIb3EgQBhLcJAgIwCgYIKoZIzj0EAwIDSAAwRQIgUpG6 +FUeWrC62BtTPHiSlWBdnLWUYH0llS6uYUkpJFJECIQCWfhoZYXvHdMhgBDSI/vzY +Sw4uNdcMxrC2kP6lIioUSw== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_invalid.pem b/crypto/x509/testdata/policy_intermediate_invalid.pem new file mode 100644 index 00000000000..11c95afcea4 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_invalid.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCCATKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjZzBlMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjAOBgNVHSAEB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIgS2uK +cYlZ1bxeqgMy3X0Sfi0arAnqpePsAqAeEf+HJHQCIQDwfCnXrWyHET9lM/gJSkfN +j/JRJvJELDrAMVewCxZWKA== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_mapped.pem b/crypto/x509/testdata/policy_intermediate_mapped.pem new file mode 100644 index 00000000000..fa45e604b43 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_mapped.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICrjCCAlSgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggGHMIIBgzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wXgYDVR0gBFcwVTAPBg0qhkiG9xIEAYS3CQIBMA8GDSqG +SIb3EgQBhLcJAgIwDwYNKoZIhvcSBAGEtwkCAzAPBg0qhkiG9xIEAYS3CQIEMA8G +DSqGSIb3EgQBhLcJAgUwgcsGA1UdIQSBwzCBwDAeBg0qhkiG9xIEAYS3CQIDBg0q +hkiG9xIEAYS3CQIBMB4GDSqGSIb3EgQBhLcJAgMGDSqGSIb3EgQBhLcJAgIwHgYN +KoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBDAeBg0qhkiG9xIEAYS3CQIEBg0q +hkiG9xIEAYS3CQIFMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3EgQBhLcJAgQwHgYN +KoZIhvcSBAGEtwkCBQYNKoZIhvcSBAGEtwkCBTAKBggqhkjOPQQDAgNIADBFAiAe +Ah2vJMZsW/RV35mM7b7/NjsjScjPEIxfDJu49inNXQIhANmGBqyWUogh/gXyVB0/ +IfDro27pANW3R02A+zH34q5k +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_mapped_any.pem b/crypto/x509/testdata/policy_intermediate_mapped_any.pem new file mode 100644 index 00000000000..ae47bf45cea --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_mapped_any.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYjCCAgegAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggE6MIIBNjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wEQYDVR0gBAowCDAGBgRVHSAAMIHLBgNVHSEEgcMwgcAw +HgYNKoZIhvcSBAGEtwkCAwYNKoZIhvcSBAGEtwkCATAeBg0qhkiG9xIEAYS3CQID +Bg0qhkiG9xIEAYS3CQICMB4GDSqGSIb3EgQBhLcJAgQGDSqGSIb3EgQBhLcJAgQw +HgYNKoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBTAeBg0qhkiG9xIEAYS3CQIF +Bg0qhkiG9xIEAYS3CQIEMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3EgQBhLcJAgUw +CgYIKoZIzj0EAwIDSQAwRgIhAIOx3GL5xlldQGdTLIvTTAvczm8wiYHzZDAif2yj +wAjEAiEAg4K02kTYX9x7PC/u1PYdwvo+LVbnGbO6AN6U3K2d7gs= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_mapped_oid3.pem b/crypto/x509/testdata/policy_intermediate_mapped_oid3.pem new file mode 100644 index 00000000000..c04a38a48f1 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_mapped_oid3.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICajCCAhCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggFDMIIBPzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIDMIHLBgNV +HSEEgcMwgcAwHgYNKoZIhvcSBAGEtwkCAwYNKoZIhvcSBAGEtwkCATAeBg0qhkiG +9xIEAYS3CQIDBg0qhkiG9xIEAYS3CQICMB4GDSqGSIb3EgQBhLcJAgQGDSqGSIb3 +EgQBhLcJAgQwHgYNKoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBTAeBg0qhkiG +9xIEAYS3CQIFBg0qhkiG9xIEAYS3CQIEMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3 +EgQBhLcJAgUwCgYIKoZIzj0EAwIDSAAwRQIhAK0bRaGgd5qQlX+zTw3IUynFHxfk +zRbZagnTzjYtkNNmAiBJ2kOnvRdW930eHAwZPGpc1Hn5hMSOQdUhNZ3XZDASkQ== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_require.pem b/crypto/x509/testdata/policy_intermediate_require.pem new file mode 100644 index 00000000000..5cf5d5bfe62 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_require.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQAwCgYIKoZIzj0EAwIDRwAwRAIgbPUZ9ezH +SgTqom7VLPOvrQQXwy3b/ijSobs7+SOouKMCIDaqcb9143BG005etqeTvlgUyOGF +GQDWhiW8bizH+KEl +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_require1.pem b/crypto/x509/testdata/policy_intermediate_require1.pem new file mode 100644 index 00000000000..7087404b3f1 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_require1.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBujCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQEwCgYIKoZIzj0EAwIDSQAwRgIhAIAwvhHB +GQDN5YXlidd+n3OT/SqoeXfp7RiEonBnCkW4AiEA+iFc47EOBchHb+Gy0gg8F9Po +RnlpoulWDfbDwx9r4lc= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_require2.pem b/crypto/x509/testdata/policy_intermediate_require2.pem new file mode 100644 index 00000000000..350f4191987 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_require2.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuTCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQIwCgYIKoZIzj0EAwIDSAAwRQIgOpliSKKA ++wy/auQnKKl+wwtn/hGw6eZXgIOtFgDmyMYCIQC84zoJL87AE64gsrdX4XSHq6lb +WhZQp9ZnDaNu88SQLQ== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_require_duplicate.pem b/crypto/x509/testdata/policy_intermediate_require_duplicate.pem new file mode 100644 index 00000000000..733087af91c --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_require_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIByjCCAXCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgaQwgaEwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMDwGA1UdIAQ1MDMwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMA8GDSqGSIb3EgQBhLcJAgIwDAYDVR0kBAUwA4ABADAKBggqhkjO +PQQDAgNIADBFAiA2GxzMRYYo7NNq8u/ZvffXkCj/phqXQ8I64tEDd0X8pgIhAOJJ +e+dzzf4vbWfMlYkOQ4kf6ei5Zf+J2PL6VrqVrHQa +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_intermediate_require_no_policies.pem b/crypto/x509/testdata/policy_intermediate_require_no_policies.pem new file mode 100644 index 00000000000..1e81e0c1165 --- /dev/null +++ b/crypto/x509/testdata/policy_intermediate_require_no_policies.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBizCCATCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjZTBjMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjAMBgNVHSQEBTADgAEAMAoGCCqGSM49BAMCA0kAMEYCIQDJYPgf +50fFDVho5TFeqkNVONx0ArVNgULPB27yPDHLrwIhAN+eua6oM4Q/O0jUESQ4VAKt +ts7ZCquTZbvgRgyqtjuT +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf.pem b/crypto/x509/testdata/policy_leaf.pem new file mode 100644 index 00000000000..fb70306c8a6 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBpzCCAU2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo34wfDAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wKwYDVR0gBCQwIjAPBg0qhkiG9xIEAYS3CQIBMA8GDSqGSIb3EgQB +hLcJAgIwCgYIKoZIzj0EAwIDSAAwRQIgBEOriD1N3/cqoAofxEtf73M7Wi4UfjFK +jiU9nQhwnnoCIQD1v/XDp2BkWNHxNq7TaPnil3xXTvMX97yUbkUg8IRo0w== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_any.pem b/crypto/x509/testdata/policy_leaf_any.pem new file mode 100644 index 00000000000..d2c1b9e9555 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_any.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjTCCATOgAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo2QwYjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wEQYDVR0gBAowCDAGBgRVHSAAMAoGCCqGSM49BAMCA0gAMEUCIQC4 +UwAf1R4HefSzyO8lyQ3fmMjkptVEhFBee0a7N12IvwIgJMYZgQ52VTbqXyXqraJ8 +V+y+o7eHds7NewqnyuLbc78= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_duplicate.pem b/crypto/x509/testdata/policy_leaf_duplicate.pem new file mode 100644 index 00000000000..bdeb13cbd68 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsTCCAVigAwIBAgIBAzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowGjEYMBYGA1UE +AxMPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkSrY +vFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1SERGnEaiNLpoc0dle +TS8wQT/cjw/wPgoeV6OBkDCBjTAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYI +KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhhbXBsZS5j +b20wPAYDVR0gBDUwMzAPBg0qhkiG9xIEAYS3CQIBMA8GDSqGSIb3EgQBhLcJAgIw +DwYNKoZIhvcSBAGEtwkCAjAKBggqhkjOPQQDAgNHADBEAiBjYDwsWcs35hU/wPqa +5gf0QUMvV/8z5LPX14fB2y4RGQIgMw0ekrt9K5UcgkvFupV/XXIjLRFQvc8URA3C +/+w+2/4= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_invalid.pem b/crypto/x509/testdata/policy_leaf_invalid.pem new file mode 100644 index 00000000000..de7a5e9b20f --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_invalid.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBgjCCASigAwIBAgIBAzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowGjEYMBYGA1UE +AxMPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkSrY +vFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1SERGnEaiNLpoc0dle +TS8wQT/cjw/wPgoeV6NhMF8wDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQMMAoGCCsG +AQUFBwMBMAwGA1UdEwEB/wQCMAAwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29t +MA4GA1UdIAQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiAgfcDIeqmV+u5YtUe4 +aBnj13tZAJAQh6ttum1xZ+xHEgIhAJqvGX5c0/d1qYelBlm/jE3UuivijdEjVsLX +GVH+X1VA +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_none.pem b/crypto/x509/testdata/policy_leaf_none.pem new file mode 100644 index 00000000000..13ad7cec017 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_none.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBezCCASCgAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo1EwTzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wCgYIKoZIzj0EAwIDSQAwRgIhAIDFeeYJ8nmYo09OnJFpNS3A6fYO +ZliHkAqOsg193DTnAiEA3OSHLCczcvRjMG+qd/FI61u2sKU1hhHh7uHtD/YO/dA= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_oid1.pem b/crypto/x509/testdata/policy_leaf_oid1.pem new file mode 100644 index 00000000000..94cd1a77b45 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_oid1.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlTCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIBMAoGCCqGSM49BAMC +A0cAMEQCIHh4Bo8l/HVJhLMWcYusPOE0arqoDrJ5E0M6nEi3nRhgAiAArK8bBohG +fZ3DmVMq/2BJtQZwRRj+50VKWuf9mBSflQ== +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_oid2.pem b/crypto/x509/testdata/policy_leaf_oid2.pem new file mode 100644 index 00000000000..10adf86c521 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_oid2.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQICMAoGCCqGSM49BAMC +A0kAMEYCIQDvW7rdL6MSW/0BPNET4hEeECO6LWmZZHKCHIu6o33dsAIhAPwgm6lD +KV2hMOxkE6rBDQzlCr+zAkQrxSzQZqJp5p+W +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_oid3.pem b/crypto/x509/testdata/policy_leaf_oid3.pem new file mode 100644 index 00000000000..e5c103151bd --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_oid3.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIDMAoGCCqGSM49BAMC +A0kAMEYCIQDBPnPpRsOH20ncg8TKUdlONfbO62WafQj9SKgyi/nGBQIhAMhT8J7f +fTEou6jlAilaIQwlAgZzVKRqgghIHezFY86T +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_oid4.pem b/crypto/x509/testdata/policy_leaf_oid4.pem new file mode 100644 index 00000000000..7dd7a547af2 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_oid4.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIEMAoGCCqGSM49BAMC +A0kAMEYCIQD2gnpCTMxUalCtEV52eXzqeJgsKMYvEpJTuU/VqH5KwQIhAPEavAkt +cSJsgMgJcJnbBzAdSrbOgHXF2etDHmFbg0hz +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_oid5.pem b/crypto/x509/testdata/policy_leaf_oid5.pem new file mode 100644 index 00000000000..2a9aee73b59 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_oid5.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIFMAoGCCqGSM49BAMC +A0kAMEYCIQDDFVjhlQ1Wu0KITcRX8kELpVDeYSKSlvEbZc3rn1QjkQIhAMPthqBi +I0acz8DPQcdFmHXV0xR2xyC1yuen0gES5WLR +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_require.pem b/crypto/x509/testdata/policy_leaf_require.pem new file mode 100644 index 00000000000..169b8444199 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_require.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo4GNMIGKMA4GA1UdDwEB/wQEAwICBDATBgNV +HSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCD3d3dy5l +eGFtcGxlLmNvbTArBgNVHSAEJDAiMA8GDSqGSIb3EgQBhLcJAgEwDwYNKoZIhvcS +BAGEtwkCAjAMBgNVHSQEBTADgAEAMAoGCCqGSM49BAMCA0kAMEYCIQDrNQPi/mdK +l7Nd/YmMXWYTHJBWWin1zA64Ohkd7z4jGgIhAJpw/umk5MxS1MwSi+YTkkcSQKpl +YROQH6+T53DauoW6 +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_leaf_require1.pem b/crypto/x509/testdata/policy_leaf_require1.pem new file mode 100644 index 00000000000..261ef954f12 --- /dev/null +++ b/crypto/x509/testdata/policy_leaf_require1.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo4GNMIGKMA4GA1UdDwEB/wQEAwICBDATBgNV +HSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCD3d3dy5l +eGFtcGxlLmNvbTArBgNVHSAEJDAiMA8GDSqGSIb3EgQBhLcJAgEwDwYNKoZIhvcS +BAGEtwkCAjAMBgNVHSQEBTADgAEBMAoGCCqGSM49BAMCA0kAMEYCIQCtXENGJrKv +IOeLHO/3Nu/SMRXc69Vb3q+4b/uHBFbuqwIhAK22Wfh/ZIHKu3FwbjL+sN0Z39pf +Dsak6fp1y4tqNuvK +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_root.pem b/crypto/x509/testdata/policy_root.pem new file mode 100644 index 00000000000..595f8a132a5 --- /dev/null +++ b/crypto/x509/testdata/policy_root.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBdTCCARqgAwIBAgIBATAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowFjEUMBIGA1UE +AxMLUG9saWN5IFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQmdqXYl1Gv +Y7y3jcTTK6MVXIQr44TqChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAP +EPSJwPndjolto1cwVTAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUH +AwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU0GnnoB+yeN63WMthnh6Uh1HH +dRIwCgYIKoZIzj0EAwIDSQAwRgIhAKVxVAaJnmvt+q4SqegGS23QSzKPM9Yakw9e +bOUU9+52AiEAjXPRBdd90YDey4VFu4f/78yVe0cxMK30lll7lLl7TTA= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_root2.pem b/crypto/x509/testdata/policy_root2.pem new file mode 100644 index 00000000000..1350035fd46 --- /dev/null +++ b/crypto/x509/testdata/policy_root2.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBeDCCAR6gAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1Qb2xpY3kg +Um9vdCAyMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAYMRYwFAYD +VQQDEw1Qb2xpY3kgUm9vdCAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJnal +2JdRr2O8t43E0yujFVyEK+OE6goUWCOiHlfbSAeoyLDmPkKJdW5PMf+wORRjp1Fh +VSxADxD0icD53Y6JbaNXMFUwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQMMAoGCCsG +AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNBp56Afsnjet1jLYZ4e +lIdRx3USMAoGCCqGSM49BAMCA0gAMEUCIQDm9rw9ODVtJUPBn2lWoK8s7ElbyY4/ +Gc2thHR50UUzbgIgKRenEDhKiBR6cGC77RaIiaaafW8b7HMd7obuZdDU/58= +-----END CERTIFICATE----- diff --git a/crypto/x509/testdata/policy_root_cross_inhibit_mapping.pem b/crypto/x509/testdata/policy_root_cross_inhibit_mapping.pem new file mode 100644 index 00000000000..9273a53086f --- /dev/null +++ b/crypto/x509/testdata/policy_root_cross_inhibit_mapping.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBljCCAT2gAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1Qb2xpY3kg +Um9vdCAyMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAWMRQwEgYD +VQQDEwtQb2xpY3kgUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCZ2pdiX +Ua9jvLeNxNMroxVchCvjhOoKFFgjoh5X20gHqMiw5j5CiXVuTzH/sDkUY6dRYVUs +QA8Q9InA+d2OiW2jeDB2MA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEF +BQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTQaeegH7J43rdYy2GeHpSH +Ucd1EjARBgNVHSAECjAIMAYGBFUdIAAwDAYDVR0kBAUwA4EBADAKBggqhkjOPQQD +AgNHADBEAiBzR3JGEf9PITYuiXTx+vx9gXji5idGsVog9wRUbY98wwIgVVeYNQQb +x+RN2wYp3kmm8iswUOrqiI6J4PSzT8CYP8Q= +-----END CERTIFICATE----- diff --git a/crypto/x509/tor_service_descriptor.go b/crypto/x509/tor_service_descriptor.go index f119ad21117..fc24e7c3870 100644 --- a/crypto/x509/tor_service_descriptor.go +++ b/crypto/x509/tor_service_descriptor.go @@ -22,7 +22,7 @@ type TorServiceDescriptorHash struct { Onion string `json:"onion"` Algorithm pkix.AlgorithmIdentifier `json:"-"` AlgorithmName string `json:"algorithm_name"` - Hash CertificateFingerprint `json:"hash"` + Hash CertificateFingerprint `json:"github.com/runZeroInc/excrypto/hash"` HashBits int `json:"hash_bits"` } diff --git a/crypto/x509/verify.go b/crypto/x509/verify.go index 07f922b8234..5bd24bcf622 100644 --- a/crypto/x509/verify.go +++ b/crypto/x509/verify.go @@ -6,10 +6,12 @@ package x509 import ( "bytes" - "errors" "fmt" + "iter" + "maps" "net" + "net/netip" "net/url" "reflect" "strings" @@ -86,6 +88,8 @@ const ( // CANotAuthorizedForExtKeyUsage results when an intermediate or root // certificate does not permit a requested extended key usage. CANotAuthorizedForExtKeyUsage + // NoValidChains results when there are no valid chains to return. + NoValidChains ) // CertificateInvalidError results when an odd error occurs. Users of this @@ -124,6 +128,12 @@ func (e CertificateInvalidError) Error() string { return "x509: issuer has name constraints but leaf doesn't have a SAN extension" case UnconstrainedName: return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail + case NoValidChains: + s := "x509: no valid chains built" + if e.Detail != "" { + s = fmt.Sprintf("%s: %s", s, e.Detail) + } + return s } return "x509: unknown error" } @@ -243,6 +253,27 @@ type VerifyOptions struct { // certificates from consuming excessive amounts of CPU time when // validating. It does not apply to the platform verifier. MaxConstraintComparisions int + + // CertificatePolicies specifies which certificate policy OIDs are + // acceptable during policy validation. An empty CertificatePolices + // field implies any valid policy is acceptable. + CertificatePolicies []OID + + // The following policy fields are unexported, because we do not expect + // users to actually need to use them, but are useful for testing the + // policy validation code. + + // inhibitPolicyMapping indicates if policy mapping should be allowed + // during path validation. + inhibitPolicyMapping bool + + // requireExplicitPolicy indidicates if explicit policies must be present + // for each certificate being validated. + requireExplicitPolicy bool + + // inhibitAnyPolicy indicates if the anyPolicy policy should be + // processed if present in a certificate being validated. + inhibitAnyPolicy bool } const ( @@ -476,8 +507,10 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { } } - if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || - net.ParseIP(host) != nil { + // netip.ParseAddr will reject the URI IPv6 literal form "[...]", so we + // check if _either_ the string parses as an IP, or if it is enclosed in + // square brackets. + if _, err := netip.ParseAddr(host); err == nil || (strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]")) { return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) } @@ -765,13 +798,6 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } } - if !boringAllowCert(c) { - // IncompatibleUsage is not quite right here, - // but it's also the "no chains found" error - // and is close enough. - return CertificateInvalidError{c, IncompatibleUsage, ""} - } - return nil } @@ -864,40 +890,42 @@ func (c *Certificate) Verify(opts VerifyOptions) (current, expired, never [][]*C if eku == ExtKeyUsageAny { // If any key usage is acceptable, no need to check the chain for // key usages. - if len(candidateChains) > 0 { - c.ValidSignature = true - } - current, expired, never = FilterByDate(candidateChains, opts.CurrentTime) - return + return candidateChains, nil, nil, nil } } chains := make([][]*Certificate, 0, len(candidateChains)) + var incompatibleKeyUsageChains, invalidPoliciesChains int for _, candidate := range candidateChains { - if checkChainForKeyUsage(candidate, opts.KeyUsages) { - chains = append(chains, candidate) + if !checkChainForKeyUsage(candidate, opts.KeyUsages) { + incompatibleKeyUsageChains++ + continue + } + if !policiesValid(candidate, opts) { + invalidPoliciesChains++ + continue } + chains = append(chains, candidate) } - if len(chains) == 0 { - err = CertificateInvalidError{c, IncompatibleUsage, "no valid chains"} - return - } - - current, expired, never = FilterByDate(chains, opts.CurrentTime) - if len(current) == 0 { - if len(expired) > 0 { - err = CertificateInvalidError{Cert: c, Reason: Expired, Detail: fmt.Sprintf("%d expired", len(expired))} - } else if len(never) > 0 { - err = CertificateInvalidError{Cert: c, Reason: NeverValid, Detail: fmt.Sprintf("%d invalid", len(never))} + var details []string + if incompatibleKeyUsageChains > 0 { + if invalidPoliciesChains == 0 { + return nil, nil, nil, CertificateInvalidError{c, IncompatibleUsage, ""} + } + details = append(details, fmt.Sprintf("%d chains with incompatible key usage", incompatibleKeyUsageChains)) } - return + if invalidPoliciesChains > 0 { + details = append(details, fmt.Sprintf("%d chains with invalid policies", invalidPoliciesChains)) + } + err = CertificateInvalidError{c, NoValidChains, strings.Join(details, ", ")} + return nil, nil, nil, err } - if len(current) > 0 { - c.ValidSignature = true - } + // Split the chains into current, expired, and never. + current, expired, never = FilterByDate(chains, opts.CurrentTime) + // TODO: Split the chains into current, expired, and never. return current, expired, never, nil } @@ -1307,3 +1335,369 @@ func FilterByDate(chains [][]*Certificate, now time.Time) (current, expired, nev } return } + +func mustNewOIDFromInts(ints []uint64) OID { + oid, err := OIDFromInts(ints) + if err != nil { + panic(fmt.Sprintf("OIDFromInts(%v) unexpected error: %v", ints, err)) + } + return oid +} + +type policyGraphNode struct { + validPolicy OID + expectedPolicySet []OID + // we do not implement qualifiers, so we don't track qualifier_set + + parents map[*policyGraphNode]bool + children map[*policyGraphNode]bool +} + +func newPolicyGraphNode(valid OID, parents []*policyGraphNode) *policyGraphNode { + n := &policyGraphNode{ + validPolicy: valid, + expectedPolicySet: []OID{valid}, + children: map[*policyGraphNode]bool{}, + parents: map[*policyGraphNode]bool{}, + } + for _, p := range parents { + p.children[n] = true + n.parents[p] = true + } + return n +} + +type policyGraph struct { + strata []map[string]*policyGraphNode + // map of OID -> nodes at strata[depth-1] with OID in their expectedPolicySet + parentIndex map[string][]*policyGraphNode + depth int +} + +var anyPolicyOID = mustNewOIDFromInts([]uint64{2, 5, 29, 32, 0}) + +func newPolicyGraph() *policyGraph { + root := policyGraphNode{ + validPolicy: anyPolicyOID, + expectedPolicySet: []OID{anyPolicyOID}, + children: map[*policyGraphNode]bool{}, + parents: map[*policyGraphNode]bool{}, + } + return &policyGraph{ + depth: 0, + strata: []map[string]*policyGraphNode{{string(anyPolicyOID.der): &root}}, + } +} + +func (pg *policyGraph) insert(n *policyGraphNode) { + pg.strata[pg.depth][string(n.validPolicy.der)] = n +} + +func (pg *policyGraph) parentsWithExpected(expected OID) []*policyGraphNode { + if pg.depth == 0 { + return nil + } + return pg.parentIndex[string(expected.der)] +} + +func (pg *policyGraph) parentWithAnyPolicy() *policyGraphNode { + if pg.depth == 0 { + return nil + } + return pg.strata[pg.depth-1][string(anyPolicyOID.der)] +} + +func (pg *policyGraph) parents() iter.Seq[*policyGraphNode] { + if pg.depth == 0 { + return nil + } + return maps.Values(pg.strata[pg.depth-1]) +} + +func (pg *policyGraph) leaves() map[string]*policyGraphNode { + return pg.strata[pg.depth] +} + +func (pg *policyGraph) leafWithPolicy(policy OID) *policyGraphNode { + return pg.strata[pg.depth][string(policy.der)] +} + +func (pg *policyGraph) deleteLeaf(policy OID) { + n := pg.strata[pg.depth][string(policy.der)] + if n == nil { + return + } + for p := range n.parents { + delete(p.children, n) + } + for c := range n.children { + delete(c.parents, n) + } + delete(pg.strata[pg.depth], string(policy.der)) +} + +func (pg *policyGraph) validPolicyNodes() []*policyGraphNode { + var validNodes []*policyGraphNode + for i := pg.depth; i >= 0; i-- { + for _, n := range pg.strata[i] { + if n.validPolicy.Equal(anyPolicyOID) { + continue + } + + if len(n.parents) == 1 { + for p := range n.parents { + if p.validPolicy.Equal(anyPolicyOID) { + validNodes = append(validNodes, n) + } + } + } + } + } + return validNodes +} + +func (pg *policyGraph) prune() { + for i := pg.depth - 1; i > 0; i-- { + for _, n := range pg.strata[i] { + if len(n.children) == 0 { + for p := range n.parents { + delete(p.children, n) + } + delete(pg.strata[i], string(n.validPolicy.der)) + } + } + } +} + +func (pg *policyGraph) incrDepth() { + pg.parentIndex = map[string][]*policyGraphNode{} + for _, n := range pg.strata[pg.depth] { + for _, e := range n.expectedPolicySet { + pg.parentIndex[string(e.der)] = append(pg.parentIndex[string(e.der)], n) + } + } + + pg.depth++ + pg.strata = append(pg.strata, map[string]*policyGraphNode{}) +} + +func policiesValid(chain []*Certificate, opts VerifyOptions) bool { + // The following code implements the policy verification algorithm as + // specified in RFC 5280 and updated by RFC 9618. In particular the + // following sections are replaced by RFC 9618: + // * 6.1.2 (a) + // * 6.1.3 (d) + // * 6.1.3 (e) + // * 6.1.3 (f) + // * 6.1.4 (b) + // * 6.1.5 (g) + + if len(chain) == 1 { + return true + } + + // n is the length of the chain minus the trust anchor + n := len(chain) - 1 + + pg := newPolicyGraph() + var inhibitAnyPolicy, explicitPolicy, policyMapping int + if !opts.inhibitAnyPolicy { + inhibitAnyPolicy = n + 1 + } + if !opts.requireExplicitPolicy { + explicitPolicy = n + 1 + } + if !opts.inhibitPolicyMapping { + policyMapping = n + 1 + } + + initialUserPolicySet := map[string]bool{} + for _, p := range opts.CertificatePolicies { + initialUserPolicySet[string(p.der)] = true + } + // If the user does not pass any policies, we consider + // that equivalent to passing anyPolicyOID. + if len(initialUserPolicySet) == 0 { + initialUserPolicySet[string(anyPolicyOID.der)] = true + } + + for i := n - 1; i >= 0; i-- { + cert := chain[i] + + isSelfSigned := bytes.Equal(cert.RawIssuer, cert.RawSubject) + + // 6.1.3 (e) -- as updated by RFC 9618 + if len(cert.Policies) == 0 { + pg = nil + } + + // 6.1.3 (f) -- as updated by RFC 9618 + if explicitPolicy == 0 && pg == nil { + return false + } + + if pg != nil { + pg.incrDepth() + + policies := map[string]bool{} + + // 6.1.3 (d) (1) -- as updated by RFC 9618 + for _, policy := range cert.Policies { + policies[string(policy.der)] = true + + if policy.Equal(anyPolicyOID) { + continue + } + + // 6.1.3 (d) (1) (i) -- as updated by RFC 9618 + parents := pg.parentsWithExpected(policy) + if len(parents) == 0 { + // 6.1.3 (d) (1) (ii) -- as updated by RFC 9618 + if anyParent := pg.parentWithAnyPolicy(); anyParent != nil { + parents = []*policyGraphNode{anyParent} + } + } + if len(parents) > 0 { + pg.insert(newPolicyGraphNode(policy, parents)) + } + } + + // 6.1.3 (d) (2) -- as updated by RFC 9618 + // NOTE: in the check "n-i < n" our i is different from the i in the specification. + // In the specification chains go from the trust anchor to the leaf, whereas our + // chains go from the leaf to the trust anchor, so our i's our inverted. Our + // check here matches the check "i < n" in the specification. + if policies[string(anyPolicyOID.der)] && (inhibitAnyPolicy > 0 || (n-i < n && isSelfSigned)) { + missing := map[string][]*policyGraphNode{} + leaves := pg.leaves() + for p := range pg.parents() { + for _, expected := range p.expectedPolicySet { + if leaves[string(expected.der)] == nil { + missing[string(expected.der)] = append(missing[string(expected.der)], p) + } + } + } + + for oidStr, parents := range missing { + pg.insert(newPolicyGraphNode(OID{der: []byte(oidStr)}, parents)) + } + } + + // 6.1.3 (d) (3) -- as updated by RFC 9618 + pg.prune() + + if i != 0 { + // 6.1.4 (b) -- as updated by RFC 9618 + if len(cert.PolicyMappings) > 0 { + // collect map of issuer -> []subject + mappings := map[string][]OID{} + + for _, mapping := range cert.PolicyMappings { + if policyMapping > 0 { + if mapping.IssuerDomainPolicy.Equal(anyPolicyOID) || mapping.SubjectDomainPolicy.Equal(anyPolicyOID) { + // Invalid mapping + return false + } + mappings[string(mapping.IssuerDomainPolicy.der)] = append(mappings[string(mapping.IssuerDomainPolicy.der)], mapping.SubjectDomainPolicy) + } else { + // 6.1.4 (b) (3) (i) -- as updated by RFC 9618 + pg.deleteLeaf(mapping.IssuerDomainPolicy) + + // 6.1.4 (b) (3) (ii) -- as updated by RFC 9618 + pg.prune() + } + } + + for issuerStr, subjectPolicies := range mappings { + // 6.1.4 (b) (1) -- as updated by RFC 9618 + if matching := pg.leafWithPolicy(OID{der: []byte(issuerStr)}); matching != nil { + matching.expectedPolicySet = subjectPolicies + } else if matching := pg.leafWithPolicy(anyPolicyOID); matching != nil { + // 6.1.4 (b) (2) -- as updated by RFC 9618 + n := newPolicyGraphNode(OID{der: []byte(issuerStr)}, []*policyGraphNode{matching}) + n.expectedPolicySet = subjectPolicies + pg.insert(n) + } + } + } + } + } + + if i != 0 { + // 6.1.4 (h) + if !isSelfSigned { + if explicitPolicy > 0 { + explicitPolicy-- + } + if policyMapping > 0 { + policyMapping-- + } + if inhibitAnyPolicy > 0 { + inhibitAnyPolicy-- + } + } + + // 6.1.4 (i) + if (cert.RequireExplicitPolicy > 0 || cert.RequireExplicitPolicyZero) && cert.RequireExplicitPolicy < explicitPolicy { + explicitPolicy = cert.RequireExplicitPolicy + } + if (cert.InhibitPolicyMapping > 0 || cert.InhibitPolicyMappingZero) && cert.InhibitPolicyMapping < policyMapping { + policyMapping = cert.InhibitPolicyMapping + } + // 6.1.4 (j) + if (cert.InhibitAnyPolicy > 0 || cert.InhibitAnyPolicyZero) && cert.InhibitAnyPolicy < inhibitAnyPolicy { + inhibitAnyPolicy = cert.InhibitAnyPolicy + } + } + } + + // 6.1.5 (a) + if explicitPolicy > 0 { + explicitPolicy-- + } + + // 6.1.5 (b) + if chain[0].RequireExplicitPolicyZero { + explicitPolicy = 0 + } + + // 6.1.5 (g) (1) -- as updated by RFC 9618 + var validPolicyNodeSet []*policyGraphNode + // 6.1.5 (g) (2) -- as updated by RFC 9618 + if pg != nil { + validPolicyNodeSet = pg.validPolicyNodes() + // 6.1.5 (g) (3) -- as updated by RFC 9618 + if currentAny := pg.leafWithPolicy(anyPolicyOID); currentAny != nil { + validPolicyNodeSet = append(validPolicyNodeSet, currentAny) + } + } + + // 6.1.5 (g) (4) -- as updated by RFC 9618 + authorityConstrainedPolicySet := map[string]bool{} + for _, n := range validPolicyNodeSet { + authorityConstrainedPolicySet[string(n.validPolicy.der)] = true + } + // 6.1.5 (g) (5) -- as updated by RFC 9618 + userConstrainedPolicySet := maps.Clone(authorityConstrainedPolicySet) + // 6.1.5 (g) (6) -- as updated by RFC 9618 + if len(initialUserPolicySet) != 1 || !initialUserPolicySet[string(anyPolicyOID.der)] { + // 6.1.5 (g) (6) (i) -- as updated by RFC 9618 + for p := range userConstrainedPolicySet { + if !initialUserPolicySet[p] { + delete(userConstrainedPolicySet, p) + } + } + // 6.1.5 (g) (6) (ii) -- as updated by RFC 9618 + if authorityConstrainedPolicySet[string(anyPolicyOID.der)] { + for policy := range initialUserPolicySet { + userConstrainedPolicySet[policy] = true + } + } + } + + if explicitPolicy == 0 && len(userConstrainedPolicySet) == 0 { + return false + } + + return true +} diff --git a/crypto/x509/verify_test.go b/crypto/x509/verify_test.go index d3af5cb3a2c..59621721c4e 100644 --- a/crypto/x509/verify_test.go +++ b/crypto/x509/verify_test.go @@ -5,11 +5,11 @@ package x509 import ( - "crypto/rand" "encoding/pem" "errors" "fmt" "math/big" + "os" "os/exec" "runtime" "slices" @@ -18,13 +18,13 @@ import ( "testing" "time" - "github.com/runZeroInc/excrypto/encoding/asn1" + "crypto/rand" "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/internal/godebug" + "github.com/runZeroInc/excrypto/encoding/asn1" "github.com/runZeroInc/excrypto/internal/testenv" ) @@ -137,45 +137,6 @@ var verifyTests = []verifyTest{ // entry so the results don't match. systemLax: true, }, - { - name: "dnssec-exp", - leaf: dnssecExpLeaf, - intermediates: []string{startComIntermediate}, - roots: []string{startComRoot}, - currentTime: 1302726541, - - // The StartCom root is not trusted by Windows when the default - // ServerAuth EKU is requested. - systemSkip: true, - - expectedChains: [][]string{ - {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, - }, - }, - { - name: "dnssec-exp/AnyEKU", - leaf: dnssecExpLeaf, - intermediates: []string{startComIntermediate}, - roots: []string{startComRoot}, - currentTime: 1302726541, - keyUsages: []ExtKeyUsage{ExtKeyUsageAny}, - - expectedChains: [][]string{ - {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, - }, - }, - { - name: "dnssec-exp/RootInIntermediates", - leaf: dnssecExpLeaf, - intermediates: []string{startComIntermediate, startComRoot}, - roots: []string{startComRoot}, - currentTime: 1302726541, - systemSkip: true, // see dnssec-exp test - - expectedChains: [][]string{ - {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, - }, - }, { name: "InvalidHash", leaf: googleLeafWithInvalidHash, @@ -230,15 +191,15 @@ var verifyTests = []verifyTest{ leaf: nameConstraintsLeaf, intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2}, roots: []string{globalSignRoot}, - currentTime: 1382387896, - dnsName: "secure.iddl.vt.edu", + currentTime: 1524771953, + dnsName: "udctest.ads.vt.edu", expectedChains: [][]string{ { - "Technology-enhanced Learning and Online Strategies", + "udctest.ads.vt.edu", "Virginia Tech Global Qualified Server CA", - "Trusted Root CA G2", - "GlobalSign Root CA", + "Trusted Root CA SHA256 G2", + "GlobalSign", }, }, }, @@ -324,7 +285,7 @@ var verifyTests = []verifyTest{ errorCallback: expectNameConstraintsError, }, - // zcrypto + // excrypto /* { // Test that unknown critical extensions in a leaf cause a @@ -500,6 +461,15 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { t.Fatalf("unexpected error: %v", err) } if test.errorCallback != nil { + // Patch in expired/never as the expired error type + if len(expired) > 0 || len(never) > 0 { + err = CertificateInvalidError{ + Cert: leaf, + Reason: Expired, + Detail: fmt.Sprintf("certificate is expired or not yet valid (current time: %s)", opts.CurrentTime), + } + } + if useSystemRoots && test.systemLax { if err == nil { t.Fatalf("expected error") @@ -561,11 +531,6 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { } func TestGoVerify(t *testing.T) { - // Temporarily enable SHA-1 verification since a number of test chains - // require it. TODO(filippo): regenerate test chains. - godebug.SetEnv("GODEBUG", "x509sha1=1") - t.Cleanup(func() { godebug.ResetEnv() }) - for _, test := range verifyTests { t.Run(test.name, func(t *testing.T) { testVerify(t, test, false) @@ -734,128 +699,6 @@ c78zEqNswn6xGKXpWF5xVwdFcsx9HKhJ6UAi2bQ/KQ1yb7LPUOR6wXXWrG1cLnNP i8eNLnKL9PXQ+5SwJFCzfEhcIZuhzg== -----END CERTIFICATE-----` -const dnssecExpLeaf = `-----BEGIN CERTIFICATE----- -MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ -TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg -MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1 -WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM -NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0 -ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw -GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt -YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4 -X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6 -D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt -RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e -7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3 -+BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG -A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM -drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw -LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC -AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB -FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB -FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr -BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp -bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh -dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw -KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig -JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF -BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v -c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh -cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE -HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB -ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y -kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM -iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ -CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm -+b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw -Qibb2+CfKuQ+WFV1GkVQmVA= ------END CERTIFICATE-----` - -const startComIntermediate = `-----BEGIN CERTIFICATE----- -MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB -jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT -IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0 -YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE -gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA -pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv -kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ -ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5 -xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID -AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov -L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0 -YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3 -dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0 -c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu -BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0 -BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl -LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp -tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen -xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw -xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X -t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI -RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi -YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L -WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN -SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD -wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L -p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un -0q6Dp6jOW6c= ------END CERTIFICATE-----` - -const startComRoot = `-----BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE-----` - const smimeLeaf = `-----BEGIN CERTIFICATE----- MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB @@ -981,168 +824,136 @@ QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE-----` var nameConstraintsLeaf = `-----BEGIN CERTIFICATE----- -MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV -BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj -MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp -cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0 -eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl -ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG -EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6 -BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg -VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu -ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0 -LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG -WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y -YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd -WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP -ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/ -psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0 -OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw -AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j -YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0 -cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl -Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD -VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV -HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0 -aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i -YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv -Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD -AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz -ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI -OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi -Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX -DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ -TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ -3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ -oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF -ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz -5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp -timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G -1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8 -GBUwDrQNTb+gsXsDkjd5lcYxNx6l +MIIG+jCCBOKgAwIBAgIQWj9gbtPPkZs65N6TKyutRjANBgkqhkiG9w0BAQsFADCB +yzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYDVQQHEwpCbGFj +a3NidXJnMSMwIQYDVQQLExpHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTE8MDoG +A1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBTdGF0ZSBV +bml2ZXJzaXR5MTEwLwYDVQQDEyhWaXJnaW5pYSBUZWNoIEdsb2JhbCBRdWFsaWZp +ZWQgU2VydmVyIENBMB4XDTE4MDQyNjE5NDU1M1oXDTE5MTIxMDAwMDAwMFowgZAx +CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tz +YnVyZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFu +ZCBTdGF0ZSBVbml2ZXJzaXR5MRswGQYDVQQDExJ1ZGN0ZXN0LmFkcy52dC5lZHUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcoVBeV3AzdSGMzRWH0tuM +VluEj+sq4r9PuLDBAdgjjHi4ED8npT2/fgOalswInXspRvFS+pkEwTrmeZ7HPzRJ +HUE5YlX5Nc6WI8ZXPVg5E6GyoMy6gNlALwqsIvDCvqxBMc39oG6yOuGmQXdF6s0N +BJMrXc4aPz60s4QMWNO2OHL0pmnZqE1TxYRBHUY/dk3cfsIepIDDuSxRsNE/P/MI +pxm/uVOyiLEnPmOMsL430SZ7nC8PxUMqya9ok6Zaf7k54g7JJXDjE96VMCjMszIv +Ud9qe1PbokTOxlG/4QW7Qm0dPbiJhTUuoBzVAxzlOOkSFdXqSYKjC9tFcbr8y+pT +AgMBAAGjggIRMIICDTCBtgYIKwYBBQUHAQEEgakwgaYwXwYIKwYBBQUHMAKGU2h0 +dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9iYWxxdWFsaWZpZWRzZXJ2ZXIvY2FjZXJ0 +L2dsb2JhbHF1YWxpZmllZHNlcnZlcl9zaGEyNTYuY3J0MEMGCCsGAQUFBzABhjdo +dHRwOi8vdnRjYS5wa2kudnQuZWR1OjgwODAvZWpiY2EvcHVibGljd2ViL3N0YXR1 +cy9vY3NwMB0GA1UdDgQWBBSzDLXee0wbgXpVQxvBQCophQDZbTAMBgNVHRMBAf8E +AjAAMB8GA1UdIwQYMBaAFLxiYCfV4zVIF+lLq0Vq0Miod3GMMGoGA1UdIARjMGEw +DgYMKwYBBAG0aAUCAgIBMA4GDCsGAQQBtGgFAgIBATA/BgwrBgEEAbRoBQICAwEw +LzAtBggrBgEFBQcCARYhaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbC9jcHMv +MEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9iYWxx +dWFsaWZpZWRzZXJ2ZXIvY3JsL2NhY3JsLmNybDAOBgNVHQ8BAf8EBAMCBeAwHQYD +VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdEQQWMBSCEnVkY3Rlc3Qu +YWRzLnZ0LmVkdTANBgkqhkiG9w0BAQsFAAOCAgEAD79kuyZbwQJCSBOVq9lA0lj4 +juHM7RMBfp2GuWvhk5F90OMKQCNdITva3oq4uQzt013TtwposYXq/d0Jobk6RHxj +OJzRZVvEPsXLvKm8oLhz7/qgI8gcVeJFR9WgdNhjN1upn++EnABHUdDR77fgixuH +FFwNC0WSZ6G0+WgYV7MKD4jYWh1DXEaJtQCN763IaWGxgvQaLUwS423xgwsx+8rw +hCRYns5u8myTbUlEu2b+GYimiogtDFMT01A7y88vKl9g+3bx42dJHQNNmSzmYPfs +IljtQbVwJIyNL/rwjoz7BTk8e9WY0qUK7ZYh+oGK8kla8yfPKtkvOJV29KdFKzTm +42kNm6cH+U5gGwEEg+Xj66Q2yFH5J9kAoBazTepgQ/13wwTY0mU9PtKVBtMH5Y/u +MoNVZz6p7vWWRrY5qSXIaW9qyF3bZnmPEHHYTplWsyAyh8blGlqPnpayDflPiQF/ +9y37kax5yhT0zPZW1ZwIZ5hDTO7pu5i83bYh3pzhvJNHtv74Nn/SX1dTZrWBi/HG +OSWK3CLz8qAEBe72XGoBjBzuk9VQxg6k52qjxCyYf7CBSQpTZhsNMf0gzu+JNATc +b+XaOqJT6uI/RfqAJVe16ZeXZIFZgQlzIwRS9vobq9fqTIpH/QxqgXROGqAlbBVp +/ByH6FEe6+oH1UCklhg= -----END CERTIFICATE-----` var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE----- -MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw -XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ -R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X -DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw -DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa -R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv -bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE -AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa -GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r -ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm -5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9 -pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM -R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz -qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W -ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+ -9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV -HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y -cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3 -Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g -BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv -YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG -A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh -dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj -cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3 -ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0 -cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn -MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0 -ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu -b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp -ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS -ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53 -aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx -MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl -bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC -FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj -b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc -c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t -YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10 -aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt -dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl -Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n -LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl -bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0 -MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp -dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu -aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k -c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0 -dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv -Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC -GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v -cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs -ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh -cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u -Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w -D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ -BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy -ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT -dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI -KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu -LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF -BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G -CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90 -cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G -A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB -AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2 -SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi -+aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp -UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd -Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB -jUY+v9vLQXmaVwI0AYL7g9LN +MIIHVTCCBj2gAwIBAgINAecHzcaPEeFvu7X4TTANBgkqhkiG9w0BAQsFADBjMQsw +CQYDVQQGEwJCRTEVMBMGA1UECxMMVHJ1c3RlZCBSb290MRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMSIwIAYDVQQDExlUcnVzdGVkIFJvb3QgQ0EgU0hBMjU2IEcy +MB4XDTE3MTIwNjAwMDAwMFoXDTIyMTIwNjAwMDAwMFowgcsxCzAJBgNVBAYTAlVT +MREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UE +CxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zpcmdpbmlh +IFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8G +A1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFG +zMXaGHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3Rh +gV+rihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmj +v7fm5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t +4lA9pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP +0YmMR3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnb +ELhzqyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyq +G66WZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYr +heq+9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3J +WqnVHNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wU +in3ycnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX00 +71s3Z2a2fio5c8m3JkdrAgMBAAGjggKdMIICmTAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAw +HQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8GA1UdIwQYMBaAFMhjmwhp +VMKYyNnN4zO3UF74yQGbMIGNBggrBgEFBQcBAQSBgDB+MDcGCCsGAQUFBzABhito +dHRwOi8vb2NzcDIuZ2xvYmFsc2lnbi5jb20vdHJ1c3Ryb290c2hhMmcyMEMGCCsG +AQUFBzAChjdodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90cnVz +dHJvb3RzaGEyZzIuY3J0MIHyBgNVHR4EgeowgeeggbIwCIEGdnQuZWR1MAmCB2Jl +di5uZXQwCoIIdmNvbS5lZHUwCIIGdnQuZWR1MAyCCnZ0Y2dpdC5jb20wd6R1MHMx +CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tz +YnVyZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFu +ZCBTdGF0ZSBVbml2ZXJzaXR5oTAwCocIAAAAAAAAAAAwIocgAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny +bC5nbG9iYWxzaWduLmNvbS9ncy90cnVzdHJvb3RzaGEyZzIuY3JsMEwGA1UdIARF +MEMwQQYJKwYBBAGgMgE8MDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2Jh +bHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQArHocpEKTv +DW1Hw0USj60KN96aLJXTLm05s0LbjloeTePtDFtuisrbE85A0IhCwxdIl/VsQMZB +7mQZBEmLzR+NK1/Luvs7C6WTmkqrE8H7D73dSOab5fMZIXS91V/aEtEQGpJMhwi1 +svd9TiiQrVkagrraeRWmTTz9BtUA3CeujuW2tShxF1ew4Q4prYw97EsE4HnKDJtu +RtyTqKsuh/rRvKMmgUdEPZbVI23yzUKhi/mTbyml/35x/f6f5p7OYIKcQ/34sts8 +xoW9dfkWBQKAXCstXat3WJVilGXBFub6GoVZdnxTDipyMZhUT/vzXq2bPphjcdR5 +YGbmwyYmChfa -----END CERTIFICATE-----` var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE----- -MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw -MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz -dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy -dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf -vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF -Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX -kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k -hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp -tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB -FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E -FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov -L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI -KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD -VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB -AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe -2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H -Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z -tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4 -RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb -hcC8roQwkHT7HvfYBoc74FM= +MIIEXDCCA0SgAwIBAgILBAAAAAABNumCOV0wDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIwNDI1MTEwMDAwWhcNMjcwNDI1 +MTEwMDAwWjBjMQswCQYDVQQGEwJCRTEVMBMGA1UECxMMVHJ1c3RlZCBSb290MRkw +FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSIwIAYDVQQDExlUcnVzdGVkIFJvb3Qg +Q0EgU0hBMjU2IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz80+ +/Q2PAhLuYwe04YTLBLGKr1/JScHtDvAY5E94GjGxCbSR1/1VhL880UPJyN85tddO +oxZPgtIyZixDvvK+CgpT5webyBBbqK/ap7aoByghAJ7X520XZMRwKA6cEWa6tjCL +WH1zscxQxGzgtV50rn2ux2SapoCPxMpM4+tpEVwWJf3KP3NT+jd9GRaXWgNei5JK +Quo9l+cZkSeuoWijvaer5hcLCufPywMMQd0r6XXIM/l7g9DjMaE24d+fa2bWxQXC +8WT/PZ+D1KUEkdtn/ixADqsoiIibGn7M84EE9/NLjbzPrwROlBUJFz6cuw+II0rZ +8OFFeZ/OkHHYZq2h9wIDAQABo4IBJjCCASIwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0 +dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMB0GA1UdDgQWBBTI +Y5sIaVTCmMjZzeMzt1Be+MkBmzA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3Js +Lmdsb2JhbHNpZ24ubmV0L3Jvb3QtcjMuY3JsMD4GCCsGAQUFBwEBBDIwMDAuBggr +BgEFBQcwAYYiaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3Jvb3RyMzAfBgNV +HSMEGDAWgBSP8Et/qC5FJK5NUPpjmove4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEA +XzbLwBjJiY6j3WEcxD3eVnsIY4pY3bl6660tgpxCuLVx4o1xyiVkS/BcQFD7GIoX +FBRrf5HibO1uSEOw0QZoRwlsio1VPg1PRaccG5C1sB51l/TL1XH5zldZBCnRYrrF +qCPorxi0xoRogj8kqkS2xyzYLElhx9X7jIzfZ8dC4mgOeoCtVvwM9xvmef3n6Vyb +7/hl3w/zWwKxWyKJNaF7tScD5nvtLUzyBpr++aztiyJ1WliWcS6W+V2gKg9rxEC/ +rc2yJS70DvfkPiEnBJ2x2AHZV3yKTALUqurkV705JledqUT9I5frAwYNXZ8pNzde +n+DIcSIo7yKy6MX9czbFWQ== -----END CERTIFICATE-----` var globalSignRoot = `-----BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f -----END CERTIFICATE-----` const digicertRoot = `-----BEGIN CERTIFICATE----- @@ -2727,7 +2538,7 @@ func TestEKUEnforcement(t *testing.T) { if err == nil && tc.err != "" { t.Errorf("expected error") } else if err != nil && err.Error() != tc.err { - t.Errorf("unexpected error: want %q, got %q", err.Error(), tc.err) + t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.err) } }) } @@ -2848,3 +2659,375 @@ func TestVerifyBareWildcard(t *testing.T) { t.Fatalf("VerifyHostname unexpected success with bare wildcard SAN") } } + +func TestPoliciesValid(t *testing.T) { + // These test cases, the comments, and the certificates they rely on, are + // stolen from BoringSSL [0]. We skip the tests which involve certificate + // parsing as part of the verification process. Those tests are in + // TestParsePolicies. + // + // [0] https://boringssl.googlesource.com/boringssl/+/264f4f7a958af6c4ccb04662e302a99dfa7c5b85/crypto/x509/x509_test.cc#5913 + + testOID1 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 1}) + testOID2 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 2}) + testOID3 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 3}) + testOID4 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 4}) + testOID5 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 5}) + + loadTestCert := func(t *testing.T, path string) *Certificate { + b, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + p, _ := pem.Decode(b) + c, err := ParseCertificate(p.Bytes) + if err != nil { + t.Fatal(err) + } + return c + } + + root := loadTestCert(t, "testdata/policy_root.pem") + root_cross_inhibit_mapping := loadTestCert(t, "testdata/policy_root_cross_inhibit_mapping.pem") + root2 := loadTestCert(t, "testdata/policy_root2.pem") + intermediate := loadTestCert(t, "testdata/policy_intermediate.pem") + intermediate_any := loadTestCert(t, "testdata/policy_intermediate_any.pem") + intermediate_mapped := loadTestCert(t, "testdata/policy_intermediate_mapped.pem") + intermediate_mapped_any := loadTestCert(t, "testdata/policy_intermediate_mapped_any.pem") + intermediate_mapped_oid3 := loadTestCert(t, "testdata/policy_intermediate_mapped_oid3.pem") + intermediate_require := loadTestCert(t, "testdata/policy_intermediate_require.pem") + intermediate_require1 := loadTestCert(t, "testdata/policy_intermediate_require1.pem") + intermediate_require2 := loadTestCert(t, "testdata/policy_intermediate_require2.pem") + intermediate_require_no_policies := loadTestCert(t, "testdata/policy_intermediate_require_no_policies.pem") + leaf := loadTestCert(t, "testdata/policy_leaf.pem") + leaf_any := loadTestCert(t, "testdata/policy_leaf_any.pem") + leaf_none := loadTestCert(t, "testdata/policy_leaf_none.pem") + leaf_oid1 := loadTestCert(t, "testdata/policy_leaf_oid1.pem") + leaf_oid2 := loadTestCert(t, "testdata/policy_leaf_oid2.pem") + leaf_oid3 := loadTestCert(t, "testdata/policy_leaf_oid3.pem") + leaf_oid4 := loadTestCert(t, "testdata/policy_leaf_oid4.pem") + leaf_oid5 := loadTestCert(t, "testdata/policy_leaf_oid5.pem") + leaf_require := loadTestCert(t, "testdata/policy_leaf_require.pem") + leaf_require1 := loadTestCert(t, "testdata/policy_leaf_require1.pem") + + type testCase struct { + chain []*Certificate + policies []OID + requireExplicitPolicy bool + inhibitPolicyMapping bool + inhibitAnyPolicy bool + valid bool + } + + tests := []testCase{ + // The chain is good for |oid1| and |oid2|, but not |oid3|. + { + chain: []*Certificate{leaf, intermediate, root}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID2}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: false, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID1, testOID2}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID1, testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + // Without |X509_V_FLAG_EXPLICIT_POLICY|, the policy tree is built and + // intersected with user-specified policies, but it is not required to result + // in any valid policies. + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID1}, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID3}, + valid: true, + }, + // However, a CA with policy constraints can require an explicit policy. + { + chain: []*Certificate{leaf, intermediate_require, root}, + policies: []OID{testOID1}, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate_require, root}, + policies: []OID{testOID3}, + valid: false, + }, + // requireExplicitPolicy applies even if the application does not configure a + // user-initial-policy-set. If the validation results in no policies, the + // chain is invalid. + { + chain: []*Certificate{leaf_none, intermediate_require, root}, + requireExplicitPolicy: true, + valid: false, + }, + // A leaf can also set requireExplicitPolicy. + { + chain: []*Certificate{leaf_require, intermediate, root}, + valid: true, + }, + { + chain: []*Certificate{leaf_require, intermediate, root}, + policies: []OID{testOID1}, + valid: true, + }, + { + chain: []*Certificate{leaf_require, intermediate, root}, + policies: []OID{testOID3}, + valid: false, + }, + // requireExplicitPolicy is a count of certificates to skip. If the value is + // not zero by the end of the chain, it doesn't count. + { + chain: []*Certificate{leaf, intermediate_require1, root}, + policies: []OID{testOID3}, + valid: false, + }, + { + chain: []*Certificate{leaf, intermediate_require2, root}, + policies: []OID{testOID3}, + valid: true, + }, + { + chain: []*Certificate{leaf_require1, intermediate, root}, + policies: []OID{testOID3}, + valid: true, + }, + // If multiple certificates specify the constraint, the more constrained value + // wins. + { + chain: []*Certificate{leaf_require1, intermediate_require1, root}, + policies: []OID{testOID3}, + valid: false, + }, + { + chain: []*Certificate{leaf_require, intermediate_require2, root}, + policies: []OID{testOID3}, + valid: false, + }, + // An intermediate that requires an explicit policy, but then specifies no + // policies should fail verification as a result. + { + chain: []*Certificate{leaf, intermediate_require_no_policies, root}, + policies: []OID{testOID1}, + valid: false, + }, + // A constrained intermediate's policy extension has a duplicate policy, which + // is invalid. + // { + // chain: []*Certificate{leaf, intermediate_require_duplicate, root}, + // policies: []OID{testOID1}, + // valid: false, + // }, + // The leaf asserts anyPolicy, but the intermediate does not. The resulting + // valid policies are the intersection. + { + chain: []*Certificate{leaf_any, intermediate, root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_any, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: false, + }, + // The intermediate asserts anyPolicy, but the leaf does not. The resulting + // valid policies are the intersection. + { + chain: []*Certificate{leaf, intermediate_any, root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf, intermediate_any, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: false, + }, + // Both assert anyPolicy. All policies are valid. + { + chain: []*Certificate{leaf_any, intermediate_any, root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_any, intermediate_any, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + // With just a trust anchor, policy checking silently succeeds. + { + chain: []*Certificate{root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: true, + }, + // Although |intermediate_mapped_oid3| contains many mappings, it only accepts + // OID3. Nodes should not be created for the other mappings. + { + chain: []*Certificate{leaf_oid1, intermediate_mapped_oid3, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid4, intermediate_mapped_oid3, root}, + policies: []OID{testOID4}, + requireExplicitPolicy: true, + valid: false, + }, + // Policy mapping can be inhibited, either by the caller or a certificate in + // the chain, in which case mapped policies are unassertable (apart from some + // anyPolicy edge cases). + { + chain: []*Certificate{leaf_oid1, intermediate_mapped_oid3, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + inhibitPolicyMapping: true, + valid: false, + }, + { + chain: []*Certificate{leaf_oid1, intermediate_mapped_oid3, root_cross_inhibit_mapping, root2}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: false, + }, + } + + for _, useAny := range []bool{false, true} { + var intermediate *Certificate + if useAny { + intermediate = intermediate_mapped_any + } else { + intermediate = intermediate_mapped + } + extraTests := []testCase{ + // OID3 is mapped to {OID1, OID2}, which means OID1 and OID2 (or both) are + // acceptable for OID3. + { + chain: []*Certificate{leaf, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid1, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid2, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: true, + }, + // If the intermediate's policies were anyPolicy, OID3 at the leaf, despite + // being mapped, is still acceptable as OID3 at the root. Despite the OID3 + // having expected_policy_set = {OID1, OID2}, it can match the anyPolicy + // node instead. + // + // If the intermediate's policies listed OIDs explicitly, OID3 at the leaf + // is not acceptable as OID3 at the root. OID3 has expected_polciy_set = + // {OID1, OID2} and no other node allows OID3. + { + chain: []*Certificate{leaf_oid3, intermediate, root}, + policies: []OID{testOID3}, + requireExplicitPolicy: true, + valid: useAny, + }, + // If the intermediate's policies were anyPolicy, OID1 at the leaf is no + // longer acceptable as OID1 at the root because policies only match + // anyPolicy when they match no other policy. + // + // If the intermediate's policies listed OIDs explicitly, OID1 at the leaf + // is acceptable as OID1 at the root because it will match both OID1 and + // OID3 (mapped) policies. + { + chain: []*Certificate{leaf_oid1, intermediate, root}, + policies: []OID{testOID1}, + requireExplicitPolicy: true, + valid: !useAny, + }, + // All pairs of OID4 and OID5 are mapped together, so either can stand for + // the other. + { + chain: []*Certificate{leaf_oid4, intermediate, root}, + policies: []OID{testOID4}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid4, intermediate, root}, + policies: []OID{testOID5}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid5, intermediate, root}, + policies: []OID{testOID4}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid5, intermediate, root}, + policies: []OID{testOID5}, + requireExplicitPolicy: true, + valid: true, + }, + { + chain: []*Certificate{leaf_oid4, intermediate, root}, + policies: []OID{testOID4, testOID5}, + requireExplicitPolicy: true, + valid: true, + }, + } + tests = append(tests, extraTests...) + } + + for i, tc := range tests { + t.Run(fmt.Sprint(i), func(t *testing.T) { + valid := policiesValid(tc.chain, VerifyOptions{ + CertificatePolicies: tc.policies, + requireExplicitPolicy: tc.requireExplicitPolicy, + inhibitPolicyMapping: tc.inhibitPolicyMapping, + inhibitAnyPolicy: tc.inhibitAnyPolicy, + }) + if valid != tc.valid { + t.Errorf("policiesValid: got %t, want %t", valid, tc.valid) + } + }) + } +} diff --git a/crypto/x509/x509.go b/crypto/x509/x509.go index a12dad2edcd..67f52b349ff 100644 --- a/crypto/x509/x509.go +++ b/crypto/x509/x509.go @@ -30,8 +30,11 @@ import ( "net" "strconv" "time" + "unicode" "github.com/runZeroInc/excrypto/crypto" + "github.com/weppos/publicsuffix-go/publicsuffix" + "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdh" "github.com/runZeroInc/excrypto/crypto/ecdsa" @@ -39,11 +42,11 @@ import ( "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/sha1" + "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/crypto/x509/ct" "github.com/runZeroInc/excrypto/crypto/x509/pkix" "github.com/runZeroInc/excrypto/encoding/asn1" "github.com/runZeroInc/excrypto/internal/godebug" - "github.com/weppos/publicsuffix-go/publicsuffix" // Explicitly import these for their crypto.RegisterHash init side-effects. // Keep these as blank imports, even if they're imported above. @@ -52,7 +55,6 @@ import ( _ "github.com/runZeroInc/excrypto/crypto/sha512" "github.com/runZeroInc/excrypto/x/crypto/cryptobyte" - cryptobyte_asn1 "github.com/runZeroInc/excrypto/x/crypto/cryptobyte/asn1" ) @@ -952,8 +954,81 @@ type Certificate struct { // cannot be represented by asn1.ObjectIdentifier, it will not be included in // PolicyIdentifiers, but will be present in Policies, which contains all parsed // policy OIDs. + // See CreateCertificate for context about how this field and the Policies field + // interact. PolicyIdentifiers []asn1.ObjectIdentifier - ValidationLevel CertValidationLevel + + // Policies contains all policy identifiers included in the certificate. + // See CreateCertificate for context about how this field and the PolicyIdentifiers field + // interact. + // In Go 1.22, encoding/gob cannot handle and ignores this field. + Policies []OID + + // InhibitAnyPolicy and InhibitAnyPolicyZero indicate the presence and value + // of the inhibitAnyPolicy extension. + // + // The value of InhibitAnyPolicy indicates the number of additional + // certificates in the path after this certificate that may use the + // anyPolicy policy OID to indicate a match with any other policy. + // + // When parsing a certificate, a positive non-zero InhibitAnyPolicy means + // that the field was specified, -1 means it was unset, and + // InhibitAnyPolicyZero being true mean that the field was explicitly set to + // zero. The case of InhibitAnyPolicy==0 with InhibitAnyPolicyZero==false + // should be treated equivalent to -1 (unset). + InhibitAnyPolicy int + // InhibitAnyPolicyZero indicates that InhibitAnyPolicy==0 should be + // interpreted as an actual maximum path length of zero. Otherwise, that + // combination is interpreted as InhibitAnyPolicy not being set. + InhibitAnyPolicyZero bool + + // InhibitPolicyMapping and InhibitPolicyMappingZero indicate the presence + // and value of the inhibitPolicyMapping field of the policyConstraints + // extension. + // + // The value of InhibitPolicyMapping indicates the number of additional + // certificates in the path after this certificate that may use policy + // mapping. + // + // When parsing a certificate, a positive non-zero InhibitPolicyMapping + // means that the field was specified, -1 means it was unset, and + // InhibitPolicyMappingZero being true mean that the field was explicitly + // set to zero. The case of InhibitPolicyMapping==0 with + // InhibitPolicyMappingZero==false should be treated equivalent to -1 + // (unset). + InhibitPolicyMapping int + // InhibitPolicyMappingZero indicates that InhibitPolicyMapping==0 should be + // interpreted as an actual maximum path length of zero. Otherwise, that + // combination is interpreted as InhibitAnyPolicy not being set. + InhibitPolicyMappingZero bool + + // RequireExplicitPolicy and RequireExplicitPolicyZero indicate the presence + // and value of the requireExplicitPolicy field of the policyConstraints + // extension. + // + // The value of RequireExplicitPolicy indicates the number of additional + // certificates in the path after this certificate before an explicit policy + // is required for the rest of the path. When an explicit policy is required, + // each subsequent certificate in the path must contain a required policy OID, + // or a policy OID which has been declared as equivalent through the policy + // mapping extension. + // + // When parsing a certificate, a positive non-zero RequireExplicitPolicy + // means that the field was specified, -1 means it was unset, and + // RequireExplicitPolicyZero being true mean that the field was explicitly + // set to zero. The case of RequireExplicitPolicy==0 with + // RequireExplicitPolicyZero==false should be treated equivalent to -1 + // (unset). + RequireExplicitPolicy int + // RequireExplicitPolicyZero indicates that RequireExplicitPolicy==0 should be + // interpreted as an actual maximum path length of zero. Otherwise, that + // combination is interpreted as InhibitAnyPolicy not being set. + RequireExplicitPolicyZero bool + + // PolicyMappings contains a list of policy mappings included in the certificate. + PolicyMappings []PolicyMapping + + ValidationLevel CertValidationLevel // Fingerprints FingerprintMD5 CertificateFingerprint @@ -988,10 +1063,6 @@ type Certificate struct { // Appendix F) TorServiceDescriptors []*TorServiceDescriptorHash - // Policies contains all policy identifiers included in the certificate. - // In Go 1.22, encoding/gob cannot handle and ignores this field. - Policies []OID - // PermissiveErrors is a list of errors encountered that were ignored PermissiveErrors []error } @@ -1049,24 +1120,26 @@ func (c *Certificate) GetParsedSubjectCommonName(invalidateCache bool) ParsedDom return *c.parsedCommonName } +// PolicyMapping represents a policy mapping entry in the policyMappings extension. +type PolicyMapping struct { + // IssuerDomainPolicy contains a policy OID the issuing certificate considers + // equivalent to SubjectDomainPolicy in the subject certificate. + IssuerDomainPolicy OID + // SubjectDomainPolicy contains a OID the issuing certificate considers + // equivalent to IssuerDomainPolicy in the subject certificate. + SubjectDomainPolicy OID +} + // ErrUnsupportedAlgorithm results from attempting to perform an operation that // involves algorithms that are not currently implemented. var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") // An InsecureAlgorithmError indicates that the [SignatureAlgorithm] used to // generate the signature is not secure, and the signature has been rejected. -// -// To temporarily restore support for SHA-1 signatures, include the value -// "x509sha1=1" in the GODEBUG environment variable. Note that this option will -// be removed in a future release. type InsecureAlgorithmError SignatureAlgorithm func (e InsecureAlgorithmError) Error() string { - var override string - if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 { - override = " (temporarily override with GODEBUG=x509sha1=1)" - } - return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override + return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) } // ConstraintViolationError results when a requested usage is not permitted by @@ -1142,8 +1215,6 @@ func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey) } -var x509sha1 = godebug.New("x509sha1") - // checkSignature verifies that signature is a valid signature over signed from // a crypto.PublicKey. // This has been modified to accept insecure signature algorithms (MD5, SHA1) @@ -1162,25 +1233,22 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey switch hashType { case crypto.Hash(0): if pubKeyAlgo != Ed25519 { - return fmt.Errorf("pubkey is not Ed25519 and has zero hash: %d: %w", pubKeyAlgo, ErrUnsupportedAlgorithm) + return ErrUnsupportedAlgorithm } - // zcrypto + // excrypto: enable weak hashing /* case crypto.MD5: return InsecureAlgorithmError(algo) case crypto.SHA1: - // SHA-1 signatures are mostly disabled. See go.dev/issue/41682. + // SHA-1 signatures are only allowed for CRLs and CSRs. if !allowSHA1 { - if x509sha1.Value() != "1" { - return InsecureAlgorithmError(algo) - } - x509sha1.IncNonDefault() + return InsecureAlgorithmError(algo) } fallthrough */ default: if !hashType.Available() { - return fmt.Errorf("hashtype is not available: %s: %w", hashType.String(), ErrUnsupportedAlgorithm) + return ErrUnsupportedAlgorithm } h := hashType.New() h.Write(signed) @@ -1525,9 +1593,14 @@ func isIA5String(s string) error { } */ -// zcrypto -// isIA5String is disabled to allow lax parsing -func isIA5String(_ string) error { +func isIA5String(s string) error { + for _, r := range s { + // Per RFC5280 "IA5String is limited to the set of ASCII characters" + if r > unicode.MaxASCII { + return fmt.Errorf("x509: %q cannot be encoded as an IA5String", s) + } + } + return nil } @@ -1618,10 +1691,7 @@ func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKe n++ } - // zcrypto - // usePolicies := x509usepolicies.Value() == "1" - usePolicies := false - + usePolicies := x509usepolicies.Value() != "0" if ((!usePolicies && len(template.PolicyIdentifiers) > 0) || (usePolicies && len(template.Policies) > 0)) && !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { ret[n], err = marshalCertificatePolicies(template.Policies, template.PolicyIdentifiers) @@ -1631,15 +1701,13 @@ func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKe n++ } - // TODO: this can be cleaned up in go1.10 - if (len(template.PermittedEmailAddresses) > 0 || len(template.PermittedDNSDomains) > 0 || len(template.PermittedDirectoryNames) > 0 || - len(template.PermittedIPRanges) > 0 || len(template.ExcludedEmailAddresses) > 0 || len(template.ExcludedDNSDomains) > 0 || - len(template.ExcludedDirectoryNames) > 0 || len(template.ExcludedIPRanges) > 0) && + if (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0 || + len(template.PermittedIPRanges) > 0 || len(template.ExcludedIPRanges) > 0 || + len(template.PermittedEmailAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 || + len(template.PermittedURIDomains) > 0 || len(template.ExcludedURIDomains) > 0) && !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) { ret[n].Id = oidExtensionNameConstraints - if template.PermittedDNSDomainsCritical { - ret[n].Critical = true - } + ret[n].Critical = template.PermittedDNSDomainsCritical ipAndMask := func(ipNet *net.IPNet) []byte { maskedIP := ipNet.IP.Mask(ipNet.Mask) @@ -1816,8 +1884,7 @@ func marshalCertificatePolicies(policies []OID, policyIdentifiers []asn1.ObjectI b := cryptobyte.NewBuilder(make([]byte, 0, 128)) b.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) { - // zcrypto - if x509usepolicies.Value() == "1" && false { // Disable for zcrypto + if x509usepolicies.Value() != "0" { x509usepolicies.IncNonDefault() for _, v := range policies { child.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) { @@ -2016,10 +2083,13 @@ var emptyASN1Subject = []byte{0x30, 0} // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId // will be generated from the hash of the public key. // -// The PolicyIdentifier and Policies fields are both used to marshal certificate -// policy OIDs. By default, only the PolicyIdentifier is marshaled, but if the -// GODEBUG setting "x509usepolicies" has the value "1", the Policies field will -// be marshaled instead of the PolicyIdentifier field. The Policies field can +// If template.SerialNumber is nil, a serial number will be generated which +// conforms to RFC 5280, Section 4.1.2.2 using entropy from rand. +// +// The PolicyIdentifier and Policies fields can both be used to marshal certificate +// policy OIDs. By default, only the Policies is marshaled, but if the +// GODEBUG setting "x509usepolicies" has the value "0", the PolicyIdentifiers field will +// be marshaled instead of the Policies field. This changed in Go 1.24. The Policies field can // be used to marshal policy OIDs which have components that are larger than 31 // bits. func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv any) ([]byte, error) { @@ -2028,25 +2098,42 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv return nil, errors.New("x509: certificate private key does not implement crypto.Signer") } - if template.SerialNumber == nil { - return nil, errors.New("x509: no SerialNumber given") + serialNumber := template.SerialNumber + if serialNumber == nil { + // Generate a serial number following RFC 5280, Section 4.1.2.2 if one + // is not provided. The serial number must be positive and at most 20 + // octets *when encoded*. + serialBytes := make([]byte, 20) + if _, err := io.ReadFull(rand, serialBytes); err != nil { + return nil, err + } + // If the top bit is set, the serial will be padded with a leading zero + // byte during encoding, so that it's not interpreted as a negative + // integer. This padding would make the serial 21 octets so we clear the + // top bit to ensure the correct length in all cases. + serialBytes[0] &= 0b0111_1111 + serialNumber = new(big.Int).SetBytes(serialBytes) } - // zcrypto + // excrypto /* - // RFC 5280 Section 4.1.2.2: serial number must positive + // RFC 5280 Section 4.1.2.2: serial number must be positive // // We _should_ also restrict serials to <= 20 octets, but it turns out a lot of people // get this wrong, in part because the encoding can itself alter the length of the // serial. For now we accept these non-conformant serials. - if template.SerialNumber.Sign() == -1 { + if serialNumber.Sign() == -1 { return nil, errors.New("x509: serial number must be positive") } - */ - if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) { - return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") - } + if template.BasicConstraintsValid && template.MaxPathLen < -1 { + return nil, errors.New("x509: invalid MaxPathLen, must be greater or equal to -1") + } + + if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) { + return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") + } + */ signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, template.SignatureAlgorithm) if err != nil { @@ -2078,12 +2165,22 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv subjectKeyId := template.SubjectKeyId if len(subjectKeyId) == 0 && template.IsCA { - // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2: - // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the - // value of the BIT STRING subjectPublicKey (excluding the tag, - // length, and number of unused bits). - h := sha1.Sum(publicKeyBytes) - subjectKeyId = h[:] + if x509sha256skid.Value() == "0" { + x509sha256skid.IncNonDefault() + // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2: + // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the + // value of the BIT STRING subjectPublicKey (excluding the tag, + // length, and number of unused bits). + h := sha1.Sum(publicKeyBytes) + subjectKeyId = h[:] + } else { + // SubjectKeyId generated using method 1 in RFC 7093, Section 2: + // 1) The keyIdentifier is composed of the leftmost 160-bits of the + // SHA-256 hash of the value of the BIT STRING subjectPublicKey + // (excluding the tag, length, and number of unused bits). + h := sha256.Sum256(publicKeyBytes) + subjectKeyId = h[:20] + } } // Check that the signer's public key matches the private key, if available. @@ -2104,7 +2201,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} c := tbsCertificate{ Version: 2, - SerialNumber: template.SerialNumber, + SerialNumber: serialNumber, SignatureAlgorithm: algorithmIdentifier, Issuer: asn1.RawValue{FullBytes: asn1Issuer}, Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, @@ -2131,6 +2228,8 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv }) } +var x509sha256skid = godebug.New("x509sha256skid") + // pemCRLPrefix is the magic string that indicates that we have a PEM encoded // CRL. var pemCRLPrefix = []byte("-----BEGIN X509 CRL") @@ -2379,10 +2478,10 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) // - Attributes (deprecated) // // priv is the private key to sign the CSR with, and the corresponding public -// key will be included in the CSR. It must implement crypto.Signer and its -// Public() method must return a *rsa.PublicKey or a *ecdsa.PublicKey or a -// ed25519.PublicKey. (A *rsa.PrivateKey, *ecdsa.PrivateKey or -// ed25519.PrivateKey satisfies this.) +// key will be included in the CSR. It must implement crypto.Signer or +// crypto.MessageSigner and its Public() method must return a *rsa.PublicKey or +// a *ecdsa.PublicKey or a ed25519.PublicKey. (A *rsa.PrivateKey, +// *ecdsa.PrivateKey or ed25519.PrivateKey satisfies this.) // // The returned slice is the certificate request in DER encoding. func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error) { @@ -2724,8 +2823,9 @@ type tbsCertificateList struct { // CreateRevocationList creates a new X.509 v2 [Certificate] Revocation List, // according to RFC 5280, based on template. // -// The CRL is signed by priv which should be the private key associated with -// the public key in the issuer certificate. +// The CRL is signed by priv which should be a crypto.Signer or +// crypto.MessageSigner associated with the public key in the issuer +// certificate. // // The issuer may not be nil, and the crlSign bit must be set in [KeyUsage] in // order to use it as a CRL issuer. diff --git a/crypto/x509/x509_test.go b/crypto/x509/x509_test.go index c89296f4805..65af8b42601 100644 --- a/crypto/x509/x509_test.go +++ b/crypto/x509/x509_test.go @@ -11,6 +11,7 @@ import ( "encoding/gob" "encoding/hex" "encoding/pem" + "errors" "fmt" "io" "math" @@ -25,8 +26,6 @@ import ( "testing" "time" - "github.com/runZeroInc/excrypto/encoding/asn1" - "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdh" @@ -37,7 +36,7 @@ import ( _ "github.com/runZeroInc/excrypto/crypto/sha256" _ "github.com/runZeroInc/excrypto/crypto/sha512" "github.com/runZeroInc/excrypto/crypto/x509/pkix" - "github.com/runZeroInc/excrypto/internal/godebug" + "github.com/runZeroInc/excrypto/encoding/asn1" "github.com/runZeroInc/excrypto/internal/testenv" ) @@ -62,6 +61,32 @@ func TestParsePKCS1PrivateKey(t *testing.T) { if _, err := ParsePKCS1PrivateKey(data); err == nil { t.Errorf("parsing invalid private key did not result in an error") } + + // A partial key without CRT values should still parse. + b, _ := asn1.Marshal(struct { + Version int + N *big.Int + E int + D *big.Int + P *big.Int + Q *big.Int + }{ + N: priv.N, + E: priv.PublicKey.E, + D: priv.D, + P: priv.Primes[0], + Q: priv.Primes[1], + }) + p2, err := ParsePKCS1PrivateKey(b) + if err != nil { + t.Fatalf("parsing partial private key resulted in an error: %v", err) + } + if !p2.Equal(priv) { + t.Errorf("partial private key did not match original key") + } + if p2.Precomputed.Dp == nil || p2.Precomputed.Dq == nil || p2.Precomputed.Qinv == nil { + t.Errorf("precomputed values not recomputed") + } } func TestPKCS1MismatchPublicKeyFormat(t *testing.T) { @@ -254,7 +279,62 @@ func TestMarshalRSAPrivateKey(t *testing.T) { priv.Primes[0].Cmp(priv2.Primes[0]) != 0 || priv.Primes[1].Cmp(priv2.Primes[1]) != 0 || priv.Primes[2].Cmp(priv2.Primes[2]) != 0 { - t.Errorf("got:%+v want:%+v", priv, priv2) + t.Errorf("wrong priv:\ngot %+v\nwant %+v", priv2, priv) + } + + if priv.Precomputed.Dp == nil { + t.Fatalf("Precomputed.Dp is nil") + } +} + +func TestMarshalRSAPrivateKeyInvalid(t *testing.T) { + block, _ := pem.Decode([]byte(strings.ReplaceAll( + `-----BEGIN RSA TESTING KEY----- +MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso +tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE +89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU +l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s +B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59 +3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+ +dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI +FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J +aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2 +BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx +IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/ +fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u +pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT +Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl +u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD +fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X +Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE +k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo +qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS +CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ +XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw +AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r +UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0 +2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5 +7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3 +-----END RSA TESTING KEY-----`, "TESTING KEY", "PRIVATE KEY"))) + testRSA2048, _ := ParsePKCS1PrivateKey(block.Bytes) + + broken := *testRSA2048 + broken.Precomputed.Dp = new(big.Int).SetUint64(42) + + parsed, err := ParsePKCS1PrivateKey(MarshalPKCS1PrivateKey(&broken)) + if err == nil { + t.Errorf("expected error, got success") + } + + t.Setenv("GODEBUG", "x509rsacrt=0") + + parsed, err = ParsePKCS1PrivateKey(MarshalPKCS1PrivateKey(&broken)) + if err != nil { + t.Fatalf("expected success, got error: %v", err) + } + // Dp should have been recomputed. + if parsed.Precomputed.Dp.Cmp(testRSA2048.Precomputed.Dp) != 0 { + t.Errorf("Dp recomputation failed: got %v, want %v", parsed.Precomputed.Dp, testRSA2048.Precomputed.Dp) } } @@ -671,18 +751,16 @@ func TestCreateSelfSignedCertificate(t *testing.T) { OCSPServer: []string{"http://ocsp.example.com"}, IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"}, - DNSNames: []string{"test.example.com"}, - EmailAddresses: []string{"gopher@golang.org"}, - IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, - URIs: []string{"https://foo.com/wibble#foo"}, - PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, - Policies: []OID{mustNewOIDFromInts(t, []uint64{1, 2, 3, math.MaxUint32, math.MaxUint64})}, - PermittedDNSDomains: []string{".example.com", "example.com"}, - ExcludedDNSDomains: []string{"bar.example.com"}, - - PermittedIPRanges: []*net.IPNet{parseCIDR("192.168.1.1/16"), parseCIDR("1.2.3.4/8")}, - ExcludedIPRanges: []*net.IPNet{parseCIDR("2001:db8::/48")}, + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + URIs: []string{"https://foo.com/wibble#foo"}, + Policies: []OID{mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxUint32, math.MaxUint64})}, + PermittedDNSDomains: []string{".example.com", "example.com"}, + ExcludedDNSDomains: []string{"bar.example.com"}, + PermittedIPRanges: []*net.IPNet{parseCIDR("192.168.1.1/16"), parseCIDR("1.2.3.4/8")}, + ExcludedIPRanges: []*net.IPNet{parseCIDR("2001:db8::/48")}, PermittedEmailAddresses: []string{"foo@example.com"}, ExcludedEmailAddresses: []string{".example.com", "example.com"}, PermittedURIDomains: []string{".bar.com", "bar.com"}, @@ -716,13 +794,12 @@ func TestCreateSelfSignedCertificate(t *testing.T) { continue } - if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) { - t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers) + if len(cert.Policies) != 1 || !cert.Policies[0].Equal(template.Policies[0]) { + t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.Policies) } - // The leading dot is trimmed - if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != "example.com" || cert.PermittedDNSDomains[1] != "example.com" { - t.Errorf("%s: failed to parse name constraints: %#v (cert:%#v)", test.name, cert.PermittedDNSDomains, cert) + if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" { + t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains) } if len(cert.ExcludedDNSDomains) != 1 || cert.ExcludedDNSDomains[0] != "bar.example.com" { @@ -1680,14 +1757,14 @@ func TestMaxPathLenNotCA(t *testing.T) { } template.MaxPathLen = 5 - if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil { - t.Error("specifying a MaxPathLen when IsCA is false should fail") + if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err != nil { + t.Error("specifying a MaxPathLen when IsCA is false should not fail") // excrypto } template.MaxPathLen = 0 template.MaxPathLenZero = true - if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil { - t.Error("setting MaxPathLenZero when IsCA is false should fail") + if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err != nil { + t.Error("setting MaxPathLenZero when IsCA is false should not fail") // excrypto } template.BasicConstraintsValid = false @@ -1822,8 +1899,8 @@ func TestInsecureAlgorithmErrorString(t *testing.T) { want string }{ {MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"}, - {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"}, - {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"}, + {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA"}, + {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1"}, {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"}, {-1, "x509: cannot verify signature: insecure algorithm -1"}, {0, "x509: cannot verify signature: insecure algorithm 0"}, @@ -1872,7 +1949,9 @@ qViorq4= -----END CERTIFICATE----- ` -func TestMD5Success(t *testing.T) { +// excrypto +/* +func TestMD5(t *testing.T) { pemBlock, _ := pem.Decode([]byte(md5cert)) cert, err := ParseCertificate(pemBlock.Bytes) if err != nil { @@ -1881,12 +1960,18 @@ func TestMD5Success(t *testing.T) { if sa := cert.SignatureAlgorithm; sa != MD5WithRSA { t.Errorf("signature algorithm is %v, want %v", sa, MD5WithRSA) } - if err = cert.CheckSignatureFrom(cert); err != nil { - t.Fatalf("certificate verification failed: %v", err) + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("certificate verification succeeded incorrectly") + } + if _, ok := err.(InsecureAlgorithmError); !ok { + t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) } } +*/ -func TestSHA1Succes(t *testing.T) { +// excrypto +/* +func TestSHA1(t *testing.T) { pemBlock, _ := pem.Decode([]byte(ecdsaSHA1CertPem)) cert, err := ParseCertificate(pemBlock.Bytes) if err != nil { @@ -1895,17 +1980,14 @@ func TestSHA1Succes(t *testing.T) { if sa := cert.SignatureAlgorithm; sa != ECDSAWithSHA1 { t.Errorf("signature algorithm is %v, want %v", sa, ECDSAWithSHA1) } - if err = cert.CheckSignatureFrom(cert); err != nil { - t.Fatalf("certificate verification failed: %v", err) + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("certificate verification succeeded incorrectly") } - - godebug.SetEnv("GODEBUG", "x509sha1=1") - t.Cleanup(func() { godebug.ResetEnv() }) - - if err = cert.CheckSignatureFrom(cert); err != nil { - t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err) + if _, ok := err.(InsecureAlgorithmError); !ok { + t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) } } +*/ // certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier // parameters are omitted rather than being an ASN.1 NULL. @@ -1924,12 +2006,17 @@ hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE GFGNEH5PlGffo05wc46QkYU= -----END CERTIFICATE-----` -func TestRSAMissingNULLParametersSuccess(t *testing.T) { +// excrypto +/* +func TestRSAMissingNULLParameters(t *testing.T) { block, _ := pem.Decode([]byte(certMissingRSANULL)) - if _, err := ParseCertificate(block.Bytes); err != nil { - t.Errorf("failed parsing certificate with missing RSA NULL parameter: %v", err) + if _, err := ParseCertificate(block.Bytes); err == nil { + t.Error("unexpected success when parsing certificate with missing RSA NULL parameter") + } else if !strings.Contains(err.Error(), "missing NULL") { + t.Errorf("unrecognised error when parsing certificate with missing RSA NULL parameter: %s", err) } } +*/ const certISOOID = `-----BEGIN CERTIFICATE----- MIIB5TCCAVKgAwIBAgIQNwyL3RPWV7dJQp34HwZG9DAJBgUrDgMCHQUAMBExDzAN @@ -2115,7 +2202,7 @@ func TestPKIXNameString(t *testing.T) { dn pkix.Name want string }{ - {nn, "1.2.3.4.5=#130a676f6c616e672e6f7267, L=Gophertown"}, + {nn, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"}, {extraNotNil, "L=Gophertown"}, {pkix.Name{ CommonName: "Steve Kille", @@ -2127,30 +2214,30 @@ func TestPKIXNameString(t *testing.T) { PostalCode: []string{"TW9 1DT"}, SerialNumber: "RFC 2253", Country: []string{"GB"}, - }, "SERIALNUMBER=RFC 2253, C=GB, POSTALCODE=TW9 1DT, ST=Surrey, L=Richmond, STREET=The Square, O=Isode Limited, OU=RFCs, CN=Steve Kille"}, + }, "SERIALNUMBER=RFC 2253,CN=Steve Kille,OU=RFCs,O=Isode Limited,POSTALCODE=TW9 1DT,STREET=The Square,L=Richmond,ST=Surrey,C=GB"}, {certs[0].Subject, - "CN=mail.google.com, O=Google LLC, L=Mountain View, ST=California, C=US"}, + "CN=mail.google.com,O=Google LLC,L=Mountain View,ST=California,C=US"}, {pkix.Name{ Organization: []string{"#Google, Inc. \n-> 'Alphabet\" "}, Country: []string{"US"}, - }, "C=US, O=\\#Google\\, Inc. \n-\\> 'Alphabet\\\"\\ "}, + }, "O=\\#Google\\, Inc. \n-\\> 'Alphabet\\\"\\ ,C=US"}, {pkix.Name{ CommonName: "foo.com", Organization: []string{"Gopher Industries"}, ExtraNames: []pkix.AttributeTypeAndValue{ {Type: asn1.ObjectIdentifier([]int{2, 5, 4, 3}), Value: "bar.com"}}, - }, "CN=bar.com, O=Gopher Industries"}, + }, "CN=bar.com,O=Gopher Industries"}, {pkix.Name{ Locality: []string{"Gophertown"}, ExtraNames: []pkix.AttributeTypeAndValue{ {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, - }, "1.2.3.4.5=#130a676f6c616e672e6f7267, L=Gophertown"}, + }, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"}, // If there are no ExtraNames, the Names are printed instead. {pkix.Name{ Locality: []string{"Gophertown"}, Names: []pkix.AttributeTypeAndValue{ {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, - }, "L=Gophertown, 1.2.3.4.5=#130a676f6c616e672e6f7267"}, + }, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"}, // If there are both, print only the ExtraNames. {pkix.Name{ Locality: []string{"Gophertown"}, @@ -2158,7 +2245,7 @@ func TestPKIXNameString(t *testing.T) { {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, Names: []pkix.AttributeTypeAndValue{ {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 6}), Value: "example.com"}}, - }, "1.2.3.4.5=#130a676f6c616e672e6f7267, L=Gophertown"}, + }, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"}, } for i, test := range tests { @@ -2200,7 +2287,7 @@ func TestRDNSequenceString(t *testing.T) { pkix.AttributeTypeAndValue{Type: oidCommonName, Value: "J. Smith"}, }, }, - want: "OU=Sales+CN=J. Smith, O=Widget Inc., C=US", + want: "OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", }, } @@ -2328,6 +2415,37 @@ func TestAdditionFieldsInGeneralSubtree(t *testing.T) { } } +func TestEmptySerialNumber(t *testing.T) { + template := Certificate{ + DNSNames: []string{"example.com"}, + } + + for range 100 { + derBytes, err := CreateCertificate(rand.Reader, &template, &template, &testPrivateKey.PublicKey, testPrivateKey) + if err != nil { + t.Fatalf("failed to create certificate: %s", err) + } + + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + + if sign := cert.SerialNumber.Sign(); sign != 1 { + t.Fatalf("generated a non positive serial, sign: %d", sign) + } + + b, err := asn1.Marshal(cert.SerialNumber) + if err != nil { + t.Fatalf("failed to marshal generated serial number: %s", err) + } + // subtract 2 for tag and length + if l := len(b) - 2; l > 20 { + t.Fatalf("generated serial number larger than 20 octets when encoded: %d", l) + } + } +} + func TestEmptySubject(t *testing.T) { template := Certificate{ SerialNumber: big.NewInt(1), @@ -2980,24 +3098,26 @@ func TestUnknownExtKey(t *testing.T) { DNSNames: []string{"foo"}, ExtKeyUsage: []ExtKeyUsage{ExtKeyUsage(-1)}, } - signer, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - t.Errorf("failed to generate key for TestUnknownExtKey") - } - _, err = CreateCertificate(rand.Reader, template, template, signer.Public(), signer) + _, err := CreateCertificate(rand.Reader, template, template, testPrivateKey.Public(), testPrivateKey) if !strings.Contains(err.Error(), errorContains) { t.Errorf("expected error containing %q, got %s", errorContains, err) } } -func TestIA5SANNonEnforcement(t *testing.T) { +// excrypto +/* +func TestIA5SANEnforcement(t *testing.T) { k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("ecdsa.GenerateKey failed: %s", err) } - testURL := "https://example.com/?∞" + testURL, err := url.Parse("https://example.com/") + if err != nil { + t.Fatalf("url.Parse failed: %s", err) + } + testURL.RawQuery = "∞" marshalTests := []struct { name string @@ -3010,6 +3130,7 @@ func TestIA5SANNonEnforcement(t *testing.T) { SerialNumber: big.NewInt(0), DNSNames: []string{"∞"}, }, + expectedError: "x509: \"∞\" cannot be encoded as an IA5String", }, { name: "marshal: unicode rfc822Name", @@ -3017,21 +3138,25 @@ func TestIA5SANNonEnforcement(t *testing.T) { SerialNumber: big.NewInt(0), EmailAddresses: []string{"∞"}, }, + expectedError: "x509: \"∞\" cannot be encoded as an IA5String", }, { name: "marshal: unicode uniformResourceIdentifier", template: &Certificate{ SerialNumber: big.NewInt(0), - URIs: []string{testURL}, + URIs: []string{testURL.String()}, }, + expectedError: "x509: \"https://example.com/?∞\" cannot be encoded as an IA5String", }, } for _, tc := range marshalTests { t.Run(tc.name, func(t *testing.T) { _, err := CreateCertificate(rand.Reader, tc.template, tc.template, k.Public(), k) - if err != nil { - t.Errorf("CreateCertificate failed with template: %v", tc.template) + if err == nil { + t.Errorf("expected CreateCertificate to fail with template: %v", tc.template) + } else if err.Error() != tc.expectedError { + t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError) } }) } @@ -3064,11 +3189,14 @@ func TestIA5SANNonEnforcement(t *testing.T) { t.Fatalf("failed to decode test cert: %s", err) } _, err = ParseCertificate(der) - if err != nil { - t.Errorf("CreateCertificate failed with template: %v", tc.name) + if err == nil { + t.Error("expected CreateCertificate to fail") + } else if err.Error() != tc.expectedError { + t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError) } } } +*/ func BenchmarkCreateCertificate(b *testing.B) { template := &Certificate{ @@ -3205,13 +3333,19 @@ func certPoolEqual(a, b *CertPool) bool { } func TestCertificateRequestRoundtripFields(t *testing.T) { - urlA := "https://example.com/_" - urlB := "https://example.org/_" + urlA, err := url.Parse("https://example.com/_") + if err != nil { + t.Fatal(err) + } + urlB, err := url.Parse("https://example.org/_") + if err != nil { + t.Fatal(err) + } in := &CertificateRequest{ DNSNames: []string{"example.com", "example.org"}, EmailAddresses: []string{"a@example.com", "b@example.com"}, IPAddresses: []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback}, - URIs: []string{urlA, urlB}, + URIs: []string{urlA.String(), urlB.String()}, } out := marshalAndParseCSR(t, in) @@ -3594,7 +3728,9 @@ func TestParseUniqueID(t *testing.T) { } } -func TestSHA1ForCertOnlySuccess(t *testing.T) { +func TestDisableSHA1ForCertOnly(t *testing.T) { + // exrypto: Enable this via debug setting + t.Setenv("GODEBUG", "") tmpl := &Certificate{ SerialNumber: big.NewInt(1), @@ -3614,9 +3750,10 @@ func TestSHA1ForCertOnlySuccess(t *testing.T) { t.Fatalf("failed to parse test cert: %s", err) } + // excrypto err = cert.CheckSignatureFrom(cert) if err != nil { - t.Errorf("CheckSignatureFrom failed: %v", err) + t.Errorf("unexpected CheckSignatureFrom fail: %v", err) } crlDER, err := CreateRevocationList(rand.Reader, &RevocationList{ @@ -3808,15 +3945,18 @@ A0cAMEQCIBzfBU5eMPT6m5lsR6cXaJILpAaiD9YxOl4v6dT3rzEjAiBHmjnHmAss RqUAyJKFzqZxOlK2q4j2IYnuj5+LrLGbQA== -----END CERTIFICATE-----` -func TestParseNegativeSerialSuccess(t *testing.T) { +// excrypto +/* +func TestParseNegativeSerial(t *testing.T) { pemBlock, _ := pem.Decode([]byte(negativeSerialCert)) _, err := ParseCertificate(pemBlock.Bytes) - if err != nil { - t.Fatalf("failed to parse certificate with negative serial: %v", err) + if err == nil { + t.Fatal("parsed certificate with negative serial") } } +*/ -// zcrypto +// excrypto /* func TestCreateNegativeSerial(t *testing.T) { k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -3907,7 +4047,10 @@ func TestDuplicateAttributesCSR(t *testing.T) { } } -func TestCertificateOIDPolicies(t *testing.T) { +func TestCertificateOIDPoliciesGODEBUG(t *testing.T) { + // excypto: Fix godebug testing for tests + t.Setenv("GODEBUG", "x509usepolicies=0") + template := Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "Cert"}, @@ -3921,7 +4064,7 @@ func TestCertificateOIDPolicies(t *testing.T) { } var expectPolicies = []OID{ - mustNewOIDFromInts(t, []uint64{1, 2, 3}), + mustNewOIDFromInts([]uint64{1, 2, 3}), } certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) @@ -3943,18 +4086,21 @@ func TestCertificateOIDPolicies(t *testing.T) { } } -/* -func TestCertificatePoliciesGODEBUG(t *testing.T) { +func TestCertificatePolicies(t *testing.T) { + if x509usepolicies.Value() == "0" { + t.Skip("test relies on default x509usepolicies GODEBUG") + } + template := Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "Cert"}, NotBefore: time.Unix(1000, 0), NotAfter: time.Unix(100000, 0), PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, - Policies: []OID{mustNewOIDFromInts(t, []uint64{1, 2, math.MaxUint32 + 1})}, + Policies: []OID{mustNewOIDFromInts([]uint64{1, 2, math.MaxUint32 + 1})}, } - expectPolicies := []OID{mustNewOIDFromInts(t, []uint64{1, 2, 3})} + expectPolicies := []OID{mustNewOIDFromInts([]uint64{1, 2, math.MaxUint32 + 1})} certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) if err != nil { t.Fatalf("CreateCertificate() unexpected error: %v", err) @@ -3969,10 +4115,8 @@ func TestCertificatePoliciesGODEBUG(t *testing.T) { t.Errorf("cert.Policies = %v, want: %v", cert.Policies, expectPolicies) } - godebug.SetEnv("GODEBUG", "x509usepolicies=1") - t.Cleanup(func() { godebug.ResetEnv() }) - - expectPolicies = []OID{mustNewOIDFromInts(t, []uint64{1, 2, math.MaxUint32 + 1})} + t.Setenv("GODEBUG", "x509usepolicies=1") + expectPolicies = []OID{mustNewOIDFromInts([]uint64{1, 2, math.MaxUint32 + 1})} certDER, err = CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) if err != nil { @@ -3988,7 +4132,6 @@ func TestCertificatePoliciesGODEBUG(t *testing.T) { t.Errorf("cert.Policies = %v, want: %v", cert.Policies, expectPolicies) } } -*/ func TestGob(t *testing.T) { // Test that gob does not reject Certificate. @@ -4074,3 +4217,73 @@ func TestRejectCriticalSKI(t *testing.T) { t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr) } } + +type messageSigner struct{} + +func (ms *messageSigner) Public() crypto.PublicKey { return rsaPrivateKey.Public() } + +func (ms *messageSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { + return nil, errors.New("unimplemented") +} + +func (ms *messageSigner) SignMessage(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { + if _, ok := opts.(*rsa.PSSOptions); ok { + return nil, errors.New("PSSOptions passed instead of hash") + } + h := opts.HashFunc().New() + h.Write(msg) + tbs := h.Sum(nil) + return rsa.SignPKCS1v15(rand, rsaPrivateKey, opts.HashFunc(), tbs) +} + +// FIX +func TestMessageSigner(t *testing.T) { + template := Certificate{ + SignatureAlgorithm: SHA256WithRSA, + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "Cert"}, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + BasicConstraintsValid: true, + IsCA: true, + } + certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), &messageSigner{}) + if err != nil { + t.Fatalf("CreateCertificate failed: %s", err) + } + cert, err := ParseCertificate(certDER) + if err != nil { + t.Fatalf("ParseCertificate failed: %s", err) + } + if err := cert.CheckSignatureFrom(cert); err != nil { + t.Fatalf("CheckSignatureFrom failed: %s", err) + } +} + +// excrypto +/* +func TestCreateCertificateNegativeMaxPathLength(t *testing.T) { + template := Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "TEST"}, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + BasicConstraintsValid: true, + IsCA: true, + + // CreateCertificate treats -1 in the same way as: MaxPathLen == 0 && MaxPathLenZero == false. + MaxPathLen: -1, + } + + _, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) + if err != nil { + t.Fatalf("CreateCertificate() unexpected error: %v", err) + } + + template.MaxPathLen = -2 + _, err = CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) + if err == nil || err.Error() != "x509: invalid MaxPathLen, must be greater or equal to -1" { + t.Fatalf(`CreateCertificate() = %v; want = "x509: invalid MaxPathLen, must be greater or equal to -1"`, err) + } +} +*/ diff --git a/crypto/x509/x509_test_import.go b/crypto/x509/x509_test_import.go index 05dba3c2de2..fc87fddbd7f 100644 --- a/crypto/x509/x509_test_import.go +++ b/crypto/x509/x509_test_import.go @@ -10,12 +10,13 @@ package main import ( - "crypto/rand" "encoding/pem" "math/big" "strings" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/x509" "github.com/runZeroInc/excrypto/crypto/x509/pkix" ) @@ -44,13 +45,19 @@ func main() { } var pemPrivateKey = testingKey(`-----BEGIN RSA TESTING KEY----- -MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 -fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu -/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu -RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ -EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A -IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS -tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +MIICXQIBAAKBgQCw0YNSqI9T1VFvRsIOejZ9feiKz1SgGfbe9Xq5tEzt2yJCsbyg ++xtcuCswNhdqY5A1ZN7G60HbL4/Hh/TlLhFJ4zNHVylz9mDDx3yp4IIcK2lb566d +fTD0B5EQ9Iqub4twLUdLKQCBfyhmJJvsEqKxm4J4QWgI+Brh/Pm3d4piPwIDAQAB +AoGASC6fj6TkLfMNdYHLQqG9kOlPfys4fstarpZD7X+fUBJ/H/7y5DzeZLGCYAIU ++QeAHWv6TfZIQjReW7Qy00RFJdgwFlTFRCsKXhG5x+IB+jL0Grr08KbgPPDgy4Jm +xirRHZVtU8lGbkiZX+omDIU28EHLNWL6rFEcTWao/tERspECQQDp2G5Nw0qYWn7H +Wm9Up1zkUTnkUkCzhqtxHbeRvNmHGKE7ryGMJEk2RmgHVstQpsvuFY4lIUSZEjAc +DUFJERhFAkEAwZH6O1ULORp8sHKDdidyleYcZU8L7y9Y3OXJYqELfddfBgFUZeVQ +duRmJj7ryu0g0uurOTE+i8VnMg/ostxiswJBAOc64Dd8uLJWKa6uug+XPr91oi0n +OFtM+xHrNK2jc+WmcSg3UJDnAI3uqMc5B+pERLq0Dc6hStehqHjUko3RnZECQEGZ +eRYWciE+Cre5dzfZkomeXE0xBrhecV0bOq6EKWLSVE+yr6mAl05ThRK9DCfPSOpy +F6rgN3QiyCA9J/1FluUCQQC5nX+PTU1FXx+6Ri2ZCi6EjEKMHr7gHcABhMinZYOt +N59pra9UdVQw9jxCU9G7eMyb0jJkNACAuEwakX3gi27b -----END RSA TESTING KEY----- `) diff --git a/crypto/x509/zintermediate/.gitignore b/crypto/x509/zintermediate/.gitignore deleted file mode 100644 index f7e9e854d1e..00000000000 --- a/crypto/x509/zintermediate/.gitignore +++ /dev/null @@ -1 +0,0 @@ -zintermediate diff --git a/crypto/x509/zintermediate/zintermediate.go b/crypto/x509/zintermediate/zintermediate.go deleted file mode 100644 index 3dd3b9e5a26..00000000000 --- a/crypto/x509/zintermediate/zintermediate.go +++ /dev/null @@ -1,212 +0,0 @@ -/* - * ZCrypto Copyright 2017 Regents of the University of Michigan - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -// ZIntermediate is a command line utility for verifying a set prospective -// intermediate certificates against a root store. Given a set of root -// certificates in PEM format, it can then read in a list of candidate -// intermediates. Candidate certificates are verified against the root store, -// and can optionally chain through any other candidate. All candidate -// certificates will be stored in memory during validation. -// -// ZIntermediate returns any candidate certificate with a chain back to the root -// store, and ignores date-related errors and extended key usage flags, meaning -// ZIntermediate will return both expired intermediates and code-signing -// certificates. -// -// While the candidate certificates can be any certificate, ZIntermediate -// expects they will be intermediates. If a non-intermediate certificate (e.g. a -// certificate without IsCA set to true) is input, ZIntermediate will not build -// chains through it, but will output it as valid. -// -// Examples: -// -// $ zintermediate --roots roots.pem candidates.csv > intermediates.pem -package main - -import ( - "bufio" - "encoding/base64" - "encoding/pem" - "errors" - "flag" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/op/go-logging" - "github.com/runZeroInc/excrypto/crypto/x509" -) - -var log = logging.MustGetLogger("") - -var inputFormatArg string - -type inputFormatType int - -const ( - inputFormatBase64 inputFormatType = iota - inputFormatPEM - inputFormatJSON -) - -var ( - inputFormat inputFormatType - inputFileName, rootFileName string -) - -func init() { - flag.StringVar(&inputFormatArg, "format", "base64", "One of {base64, pem, json}") - flag.StringVar(&rootFileName, "roots", "roots.pem", "Path to root store") - flag.Parse() - - if flag.NArg() < 1 { - log.Fatalf("missing filename") - } - inputFileName = flag.Arg(0) - - inputFormatArg = strings.ToLower(inputFormatArg) - switch inputFormatArg { - case "base64": - inputFormat = inputFormatBase64 - case "pem": - inputFormat = inputFormatPEM - case "json": - inputFormat = inputFormatJSON - default: - log.Fatalf("unknown argument for --format %q, see --help", inputFormatArg) - } -} - -func loadPEMPool(r io.Reader) (*x509.CertPool, error) { - out := x509.NewCertPool() - scanner := bufio.NewScanner(r) - - scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) { - block, rest := pem.Decode(data) - if block != nil { - size := len(data) - len(rest) - return size, data[:size], nil - } - return 0, nil, nil - }) - - for scanner.Scan() { - pemBytes := scanner.Bytes() - ok := out.AppendCertsFromPEM(pemBytes) - if !ok { - log.Errorf("could not load PEM: %s", scanner.Text()) - return nil, errors.New("unable to load PEM") - } - } - return out, nil -} - -func loadBase64Pool(r io.Reader) (*x509.CertPool, error) { - out := x509.NewCertPool() - scanner := bufio.NewScanner(r) - scanner.Buffer(nil, 1024*1024*10) - var lines int - for lines = 0; scanner.Scan(); lines += 1 { - line := scanner.Text() - raw, err := base64.StdEncoding.DecodeString(line) - if err != nil { - log.Errorf("could not read base64: %s", line) - return nil, err - } - c, err := x509.ParseCertificate(raw) - if err != nil { - log.Errorf("could not read certificate %s: %s", line, err) - continue - } - out.AddCert(c) - } - if err := scanner.Err(); err != nil { - log.Fatalf("%s", err) - } - log.Infof("read %d lines", lines) - return out, nil -} - -func main() { - log.Infof("loading roots from %s", rootFileName) - rootFile, err := os.Open(rootFileName) - if err != nil { - log.Fatalf("could not open %s: %s", rootFileName, err) - } - rootPool, err := loadPEMPool(rootFile) - rootFile.Close() - if err != nil { - log.Fatalf("could not load roots: %s", err) - } - - log.Infof("loading candidate intermediates from %s", inputFileName) - intermediateFile, err := os.Open(inputFileName) - if err != nil { - log.Fatalf("could not open %s: %s", inputFileName, err) - } - log.Infof("using input format type %s", inputFormatArg) - var candidatePool *x509.CertPool - switch inputFormat { - case inputFormatPEM: - candidatePool, err = loadPEMPool(intermediateFile) - case inputFormatBase64: - candidatePool, err = loadBase64Pool(intermediateFile) - default: - err = fmt.Errorf("unimplemented input type: %s", inputFormatArg) - } - intermediateFile.Close() - - if err != nil { - log.Fatalf("could not load candidate intermediates: %s", err) - } - candidates := candidatePool.Certificates() - log.Infof("loaded %d candidates", len(candidates)) - - now := time.Now() - verifyOpts := x509.VerifyOptions{ - Roots: rootPool, - Intermediates: candidatePool, - CurrentTime: now, - KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, - } - - log.Infof("validating candidates") - intermediates := make([]*x509.Certificate, 0) - rejected := 0 - for idx, candidate := range candidates { - if idx > 0 && idx%1000 == 0 { - log.Infof("checked %d candidates", idx) - } - if current, expired, never, _ := candidate.Verify(verifyOpts); len(current) > 0 || len(expired) > 0 || len(never) > 0 { - intermediates = append(intermediates, candidate) - continue - } - rejected++ - } - log.Infof("validation complete") - log.Infof("found %d intermediates", len(intermediates)) - log.Infof("rejected %d candidates", rejected) - - log.Infof("outputing intermediates") - for _, c := range intermediates { - block := pem.Block{ - Type: "CERTIFICATE", - Bytes: c.Raw, - } - _ = pem.Encode(os.Stdout, &block) - } - log.Infof("complete") -} diff --git a/encoding/asn1/asn1.go b/encoding/asn1/asn1.go index 2e988f2e6e0..745d20c0435 100644 --- a/encoding/asn1/asn1.go +++ b/encoding/asn1/asn1.go @@ -25,6 +25,7 @@ import ( "math" "math/big" "reflect" + "slices" "strconv" "strings" "time" @@ -86,10 +87,8 @@ func checkInteger(bytes []byte) error { if len(bytes) == 1 { return nil } - if !AllowPermissiveParsing { - if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) { - return StructuralError{"integer not minimally-encoded"} - } + if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) { + return StructuralError{"integer not minimally-encoded"} } return nil } @@ -229,16 +228,7 @@ type ObjectIdentifier []int // Equal reports whether oi and other represent the same identifier. func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool { - if len(oi) != len(other) { - return false - } - for i := 0; i < len(oi); i++ { - if oi[i] != other[i] { - return false - } - } - - return true + return slices.Equal(oi, other) } func (oi ObjectIdentifier) String() string { @@ -483,7 +473,21 @@ func parseIA5String(bytes []byte) (ret string, err error) { // parseT61String parses an ASN.1 T61String (8-bit clean string) from the given // byte slice and returns it. func parseT61String(bytes []byte) (ret string, err error) { - return string(bytes), nil + // T.61 is a defunct ITU 8-bit character encoding which preceded Unicode. + // T.61 uses a code page layout that _almost_ exactly maps to the code + // page layout of the ISO 8859-1 (Latin-1) character encoding, with the + // exception that a number of characters in Latin-1 are not present + // in T.61. + // + // Instead of mapping which characters are present in Latin-1 but not T.61, + // we just treat these strings as being encoded using Latin-1. This matches + // what most of the world does, including BoringSSL. + buf := make([]byte, 0, len(bytes)) + for _, v := range bytes { + // All the 1-byte UTF-8 runes map 1-1 with Latin-1. + buf = utf8.AppendRune(buf, rune(v)) + } + return string(buf), nil } // UTF8String @@ -504,8 +508,16 @@ func parseUTF8String(bytes []byte) (ret string, err error) { // parseBMPString parses an ASN.1 BMPString (Basic Multilingual Plane of // ISO/IEC/ITU 10646-1) from the given byte slice and returns it. func parseBMPString(bmpString []byte) (string, error) { + // BMPString uses the defunct UCS-2 16-bit character encoding, which + // covers the Basic Multilingual Plane (BMP). UTF-16 was an extension of + // UCS-2, containing all of the same code points, but also including + // multi-code point characters (by using surrogate code points). We can + // treat a UCS-2 encoded string as a UTF-16 encoded string, as long as + // we reject out the UTF-16 specific code points. This matches the + // BoringSSL behavior. + if len(bmpString)%2 != 0 { - return "", errors.New("pkcs12: odd-length BMP string") + return "", errors.New("invalid BMPString") } // Strip terminator if present. @@ -515,7 +527,16 @@ func parseBMPString(bmpString []byte) (string, error) { s := make([]uint16, 0, len(bmpString)/2) for len(bmpString) > 0 { - s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) + point := uint16(bmpString[0])<<8 + uint16(bmpString[1]) + // Reject UTF-16 code points that are permanently reserved + // noncharacters (0xfffe, 0xffff, and 0xfdd0-0xfdef) and surrogates + // (0xd800-0xdfff). + if point == 0xfffe || point == 0xffff || + (point >= 0xfdd0 && point <= 0xfdef) || + (point >= 0xd800 && point <= 0xdfff) { + return "", errors.New("invalid BMPString") + } + s = append(s, point) bmpString = bmpString[2:] } @@ -606,13 +627,10 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i return } } - - if !AllowPermissiveParsing { - // Short lengths must be encoded in short form. - if ret.length < 0x80 { - err = StructuralError{"non-minimal length"} - return - } + // Short lengths must be encoded in short form. + if ret.length < 0x80 { + err = StructuralError{"non-minimal length"} + return } } @@ -719,6 +737,8 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam if !t.isCompound && t.class == ClassUniversal { innerBytes := bytes[offset : offset+t.length] switch t.tag { + case TagBoolean: + result, err = parseBool(innerBytes) case TagPrintableString: result, err = parsePrintableString(innerBytes) case TagNumericString: @@ -820,9 +840,18 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam } // Special case for time: UTCTime and GeneralizedTime both map to the - // Go type time.Time. - if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal { - universalTag = TagGeneralizedTime + // Go type time.Time. getUniversalType returns the tag for UTCTime when + // it sees a time.Time, so if we see a different time type on the wire, + // or the field is tagged with a different type, we change the universal + // type to match. + if universalTag == TagUTCTime { + if t.class == ClassUniversal { + if t.tag == TagGeneralizedTime { + universalTag = t.tag + } + } else if params.timeType != 0 { + universalTag = params.timeType + } } if params.set { @@ -1095,6 +1124,13 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { // numeric causes strings to be unmarshaled as ASN.1 NumericString values // utf8 causes strings to be unmarshaled as ASN.1 UTF8String values // +// When decoding an ASN.1 value with an IMPLICIT tag into a time.Time field, +// Unmarshal will default to a UTCTime, which doesn't support time zones or +// fractional seconds. To force usage of GeneralizedTime, use the following +// tag: +// +// generalized causes time.Times to be unmarshaled as ASN.1 GeneralizedTime values +// // If the type of the first field of a structure is RawContent then the raw // ASN1 contents of the struct will be stored in it. // diff --git a/encoding/asn1/marshal.go b/encoding/asn1/marshal.go index b9c0b8bce05..70e4fafc123 100644 --- a/encoding/asn1/marshal.go +++ b/encoding/asn1/marshal.go @@ -725,6 +725,7 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { // omitempty: causes empty slices to be skipped // printable: causes strings to be marshaled as ASN.1, PrintableString values // utf8: causes strings to be marshaled as ASN.1, UTF8String values +// numeric: causes strings to be marshaled as ASN.1, NumericString values // utc: causes time.Time to be marshaled as ASN.1, UTCTime values // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values func Marshal(val any) ([]byte, error) { diff --git a/go.mod b/go.mod index 9004645be60..800d4bbab49 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/runZeroInc/excrypto -go 1.23.1 +go 1.24.0 require ( - github.com/google/go-cmp v0.6.0 + github.com/google/go-cmp v0.7.0 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 - github.com/stretchr/testify v1.10.0 - github.com/weppos/publicsuffix-go v0.40.2 - golang.org/x/crypto v0.33.0 - golang.org/x/sys v0.30.0 - golang.org/x/term v0.29.0 + github.com/stretchr/testify v1.11.1 + github.com/weppos/publicsuffix-go v0.50.0 + golang.org/x/crypto v0.42.0 + golang.org/x/sys v0.36.0 + golang.org/x/term v0.35.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 ) @@ -18,7 +18,7 @@ require ( github.com/kr/pretty v0.1.0 // indirect github.com/kr/text v0.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.35.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/text v0.29.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 46c85be8e7e..5e504dc7d95 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,7 @@ -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= -github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -24,106 +11,23 @@ github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0C github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/weppos/publicsuffix-go v0.40.2 h1:LlnoSH0Eqbsi3ReXZWBKCK5lHyzf3sc1JEHH1cnlfho= -github.com/weppos/publicsuffix-go v0.40.2/go.mod h1:XsLZnULC3EJ1Gvk9GVjuCTZ8QUu9ufE4TZpOizDShko= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/weppos/publicsuffix-go v0.50.0 h1:M178k6l8cnh9T1c1cStkhytVxdk5zPd6gGZf8ySIuVo= +github.com/weppos/publicsuffix-go v0.50.0/go.mod h1:VXhClBYMlDrUsome4pOTpe68Ui0p6iQRAbyHQD1yKoU= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/hash/example_test.go b/hash/example_test.go new file mode 100644 index 00000000000..f07b9aaa2c4 --- /dev/null +++ b/hash/example_test.go @@ -0,0 +1,51 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hash_test + +import ( + "bytes" + "crypto/sha256" + "encoding" + "fmt" + "log" +) + +func Example_binaryMarshaler() { + const ( + input1 = "The tunneling gopher digs downwards, " + input2 = "unaware of what he will find." + ) + + first := sha256.New() + first.Write([]byte(input1)) + + marshaler, ok := first.(encoding.BinaryMarshaler) + if !ok { + log.Fatal("first does not implement encoding.BinaryMarshaler") + } + state, err := marshaler.MarshalBinary() + if err != nil { + log.Fatal("unable to marshal hash:", err) + } + + second := sha256.New() + + unmarshaler, ok := second.(encoding.BinaryUnmarshaler) + if !ok { + log.Fatal("second does not implement encoding.BinaryUnmarshaler") + } + if err := unmarshaler.UnmarshalBinary(state); err != nil { + log.Fatal("unable to unmarshal hash:", err) + } + + first.Write([]byte(input2)) + second.Write([]byte(input2)) + + fmt.Printf("%x\n", first.Sum(nil)) + fmt.Println(bytes.Equal(first.Sum(nil), second.Sum(nil))) + // Output: + // 57d51a066f3a39942649cd9a76c77e97ceab246756ff3888659e6aa5a07f4a52 + // true +} diff --git a/hash/hash.go b/hash/hash.go new file mode 100644 index 00000000000..24ee9929c95 --- /dev/null +++ b/hash/hash.go @@ -0,0 +1,92 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package hash provides interfaces for hash functions. +package hash + +import "io" + +// Hash is the common interface implemented by all hash functions. +// +// Hash implementations in the standard library (e.g. [hash/crc32] and +// [crypto/sha256]) implement the [encoding.BinaryMarshaler], [encoding.BinaryAppender], +// [encoding.BinaryUnmarshaler] and [Cloner] interfaces. Marshaling a hash implementation +// allows its internal state to be saved and used for additional processing +// later, without having to re-write the data previously written to the hash. +// The hash state may contain portions of the input in its original form, +// which users are expected to handle for any possible security implications. +// +// Compatibility: Any future changes to hash or crypto packages will endeavor +// to maintain compatibility with state encoded using previous versions. +// That is, any released versions of the packages should be able to +// decode data written with any previously released version, +// subject to issues such as security fixes. +// See the Go compatibility document for background: https://golang.org/doc/go1compat +type Hash interface { + // Write (via the embedded io.Writer interface) adds more data to the running hash. + // It never returns an error. + io.Writer + + // Sum appends the current hash to b and returns the resulting slice. + // It does not change the underlying hash state. + Sum(b []byte) []byte + + // Reset resets the Hash to its initial state. + Reset() + + // Size returns the number of bytes Sum will return. + Size() int + + // BlockSize returns the hash's underlying block size. + // The Write method must be able to accept any amount + // of data, but it may operate more efficiently if all writes + // are a multiple of the block size. + BlockSize() int +} + +// Hash32 is the common interface implemented by all 32-bit hash functions. +type Hash32 interface { + Hash + Sum32() uint32 +} + +// Hash64 is the common interface implemented by all 64-bit hash functions. +type Hash64 interface { + Hash + Sum64() uint64 +} + +// A Cloner is a hash function whose state can be cloned, returning a value with +// equivalent and independent state. +// +// All [Hash] implementations in the standard library implement this interface, +// unless GOFIPS140=v1.0.0 is set. +// +// If a hash can only determine at runtime if it can be cloned (e.g. if it wraps +// another hash), Clone may return an error wrapping [errors.ErrUnsupported]. +// Otherwise, Clone must always return a nil error. +type Cloner interface { + Hash + Clone() (Cloner, error) +} + +// XOF (extendable output function) is a hash function with arbitrary or unlimited output length. +type XOF interface { + // Write absorbs more data into the XOF's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the XOF. It may return io.EOF if there + // is a limit to the XOF output length. + io.Reader + + // Reset resets the XOF to its initial state. + Reset() + + // BlockSize returns the XOF's underlying block size. + // The Write method must be able to accept any amount + // of data, but it may operate more efficiently if all writes + // are a multiple of the block size. + BlockSize() int +} diff --git a/hash/marshal_test.go b/hash/marshal_test.go new file mode 100644 index 00000000000..bcbccd35378 --- /dev/null +++ b/hash/marshal_test.go @@ -0,0 +1,108 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that the hashes in the standard library implement +// BinaryMarshaler, BinaryUnmarshaler, +// and lock in the current representations. + +package hash_test + +import ( + "bytes" + "encoding" + "encoding/hex" + "hash/adler32" + "hash/crc32" + "hash/crc64" + "hash/fnv" + "testing" + + "github.com/runZeroInc/excrypto/crypto/md5" + "github.com/runZeroInc/excrypto/crypto/sha1" + "github.com/runZeroInc/excrypto/crypto/sha256" + "github.com/runZeroInc/excrypto/crypto/sha512" + "github.com/runZeroInc/excrypto/hash" +) + +func fromHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +var marshalTests = []struct { + name string + new func() hash.Hash + golden []byte +}{ + {"adler32", func() hash.Hash { return adler32.New() }, fromHex("61646c01460a789d")}, + {"crc32", func() hash.Hash { return crc32.NewIEEE() }, fromHex("63726301ca87914dc956d3e8")}, + {"crc64", func() hash.Hash { return crc64.New(crc64.MakeTable(crc64.ISO)) }, fromHex("6372630273ba8484bbcd5def5d51c83c581695be")}, + {"fnv32", func() hash.Hash { return fnv.New32() }, fromHex("666e760171ba3d77")}, + {"fnv32a", func() hash.Hash { return fnv.New32a() }, fromHex("666e76027439f86f")}, + {"fnv64", func() hash.Hash { return fnv.New64() }, fromHex("666e7603cc64e0e97692c637")}, + {"fnv64a", func() hash.Hash { return fnv.New64a() }, fromHex("666e7604c522af9b0dede66f")}, + {"fnv128", func() hash.Hash { return fnv.New128() }, fromHex("666e760561587a70a0f66d7981dc980e2cabbaf7")}, + {"fnv128a", func() hash.Hash { return fnv.New128a() }, fromHex("666e7606a955802b0136cb67622b461d9f91e6ff")}, + {"md5", md5.New, fromHex("6d643501a91b0023007aa14740a3979210b5f024c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha1", sha1.New, fromHex("736861016dad5acb4dc003952f7a0b352ee5537ec381a228c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha224", sha256.New224, fromHex("73686102f8b92fc047c9b4d82f01a6370841277b7a0d92108440178c83db855a8e66c2d9c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha256", sha256.New, fromHex("736861032bed68b99987cae48183b2b049d393d0050868e4e8ba3730e9112b08765929b7c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha384", sha512.New384, fromHex("736861046f1664d213dd802f7c47bc50637cf93592570a2b8695839148bf38341c6eacd05326452ef1cbe64d90f1ef73bb5ac7d2803565467d0ddb10c5ee3fc050f9f0c1808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha512_224", sha512.New512_224, fromHex("736861056f1a450ec15af20572d0d1ee6518104d7cbbbe79a038557af5450ed7dbd420b53b7335209e951b4d9aff401f90549b9604fa3d823fbb8581c73582a88aa84022808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha512_256", sha512.New512_256, fromHex("736861067c541f1d1a72536b1f5dad64026bcc7c508f8a2126b51f46f8b9bff63a26fee70980718031e96832e95547f4fe76160ff84076db53b4549b86354af8e17b5116808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, + {"sha512", sha512.New, fromHex("736861078e03953cd57cd6879321270afa70c5827bb5b69be59a8f0130147e94f2aedf7bdc01c56c92343ca8bd837bb7f0208f5a23e155694516b6f147099d491a30b151808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f80000000000000000000000000000f9")}, +} + +func TestMarshalHash(t *testing.T) { + for _, tt := range marshalTests { + t.Run(tt.name, func(t *testing.T) { + buf := make([]byte, 256) + for i := range buf { + buf[i] = byte(i) + } + + h := tt.new() + h.Write(buf[:256]) + sum := h.Sum(nil) + + h2 := tt.new() + h3 := tt.new() + const split = 249 + for i := 0; i < split; i++ { + h2.Write(buf[i : i+1]) + } + h2m, ok := h2.(encoding.BinaryMarshaler) + if !ok { + t.Fatalf("Hash does not implement MarshalBinary") + } + enc, err := h2m.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary: %v", err) + } + if !bytes.Equal(enc, tt.golden) { + t.Errorf("MarshalBinary = %x, want %x", enc, tt.golden) + } + h3u, ok := h3.(encoding.BinaryUnmarshaler) + if !ok { + t.Fatalf("Hash does not implement UnmarshalBinary") + } + if err := h3u.UnmarshalBinary(enc); err != nil { + t.Fatalf("UnmarshalBinary: %v", err) + } + h2.Write(buf[split:]) + h3.Write(buf[split:]) + sum2 := h2.Sum(nil) + sum3 := h3.Sum(nil) + if !bytes.Equal(sum2, sum) { + t.Fatalf("Sum after MarshalBinary = %x, want %x", sum2, sum) + } + if !bytes.Equal(sum3, sum) { + t.Fatalf("Sum after UnmarshalBinary = %x, want %x", sum3, sum) + } + }) + } +} diff --git a/hash/test_cases.txt b/hash/test_cases.txt new file mode 100644 index 00000000000..26d3ccc0524 --- /dev/null +++ b/hash/test_cases.txt @@ -0,0 +1,31 @@ + +a +ab +abc +abcd +abcde +abcdef +abcdefg +abcdefgh +abcdefghi +abcdefghij +Discard medicine more than two years old. +He who has a shady past knows that nice guys finish last. +I wouldn't marry him with a ten foot pole. +Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave +The days of the digital watch are numbered. -Tom Stoppard +Nepal premier won't resign. +For every action there is an equal and opposite government program. +His money is twice tainted: 'taint yours and 'taint mine. +There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977 +It's a tiny change to the code and not completely disgusting. - Bob Manchek +size: a.out: bad magic +The major problem is with sendmail. -Mark Horton +Give me a rock, paper and scissors and I will move the world. CCFestoon +If the enemy is within range, then so are you. +It's well we cannot hear the screams/That we create in others' dreams. +You remind me of a TV show, but that's all right: I watch it anyway. +C is as portable as Stonehedge!! +Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley +The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule +How can you write a big system without C++? -Paul Glick diff --git a/hash/test_gen.awk b/hash/test_gen.awk new file mode 100644 index 00000000000..804f786795f --- /dev/null +++ b/hash/test_gen.awk @@ -0,0 +1,14 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# awk -f test_gen.awk test_cases.txt +# generates test case table. +# edit next line to set particular reference implementation and name. +BEGIN { cmd = "echo -n `9 sha1sum`"; name = "Sha1Test" } +{ + printf("\t%s{ \"", name); + printf("%s", $0) |cmd; + close(cmd); + printf("\", \"%s\" },\n", $0); +} diff --git a/internal/byteorder/byteorder.go b/internal/byteorder/byteorder.go index ba37856ccd9..a3fee51e15f 100644 --- a/internal/byteorder/byteorder.go +++ b/internal/byteorder/byteorder.go @@ -10,12 +10,18 @@ func LeUint16(b []byte) uint16 { _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 return uint16(b[0]) | uint16(b[1])<<8 } +func LEUint16(b []byte) uint16 { + return LeUint16(b) +} func LePutUint16(b []byte, v uint16) { _ = b[1] // early bounds check to guarantee safety of writes below b[0] = byte(v) b[1] = byte(v >> 8) } +func LEPutUint16(b []byte, v uint16) { + LePutUint16(b, v) +} func LeAppendUint16(b []byte, v uint16) []byte { return append(b, @@ -23,11 +29,17 @@ func LeAppendUint16(b []byte, v uint16) []byte { byte(v>>8), ) } +func LEAppendPutUint16(b []byte, v uint16) []byte { + return LeAppendUint16(b, v) +} func LeUint32(b []byte) uint32 { _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 } +func LEUint32(b []byte) uint32 { + return LeUint32(b) +} func LePutUint32(b []byte, v uint32) { _ = b[3] // early bounds check to guarantee safety of writes below @@ -36,6 +48,9 @@ func LePutUint32(b []byte, v uint32) { b[2] = byte(v >> 16) b[3] = byte(v >> 24) } +func LEPutUint32(b []byte, v uint32) { + LePutUint32(b, v) +} func LeAppendUint32(b []byte, v uint32) []byte { return append(b, @@ -45,12 +60,18 @@ func LeAppendUint32(b []byte, v uint32) []byte { byte(v>>24), ) } +func LEAppendUint32(b []byte, v uint32) []byte { + return LeAppendUint32(b, v) +} func LeUint64(b []byte) uint64 { _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 } +func LEUint64(b []byte) uint64 { + return LeUint64(b) +} func LePutUint64(b []byte, v uint64) { _ = b[7] // early bounds check to guarantee safety of writes below @@ -63,6 +84,9 @@ func LePutUint64(b []byte, v uint64) { b[6] = byte(v >> 48) b[7] = byte(v >> 56) } +func LEPutUint64(b []byte, v uint64) { + LePutUint64(b, v) +} func LeAppendUint64(b []byte, v uint64) []byte { return append(b, @@ -76,17 +100,26 @@ func LeAppendUint64(b []byte, v uint64) []byte { byte(v>>56), ) } +func LEAppendUint64(b []byte, v uint64) []byte { + return LeAppendUint64(b, v) +} func BeUint16(b []byte) uint16 { _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 return uint16(b[1]) | uint16(b[0])<<8 } +func BEUint16(b []byte) uint16 { + return BeUint16(b) +} func BePutUint16(b []byte, v uint16) { _ = b[1] // early bounds check to guarantee safety of writes below b[0] = byte(v >> 8) b[1] = byte(v) } +func BEPutUint16(b []byte, v uint16) { + BePutUint16(b, v) +} func BeAppendUint16(b []byte, v uint16) []byte { return append(b, @@ -94,11 +127,17 @@ func BeAppendUint16(b []byte, v uint16) []byte { byte(v), ) } +func BEAppendUint16(b []byte, v uint16) []byte { + return BeAppendUint16(b, v) +} func BeUint32(b []byte) uint32 { _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 } +func BEUint32(b []byte) uint32 { + return BeUint32(b) +} func BePutUint32(b []byte, v uint32) { _ = b[3] // early bounds check to guarantee safety of writes below @@ -107,6 +146,9 @@ func BePutUint32(b []byte, v uint32) { b[2] = byte(v >> 8) b[3] = byte(v) } +func BEPutUint32(b []byte, v uint32) { + BePutUint32(b, v) +} func BeAppendUint32(b []byte, v uint32) []byte { return append(b, @@ -116,12 +158,18 @@ func BeAppendUint32(b []byte, v uint32) []byte { byte(v), ) } +func BEAppendUint32(b []byte, v uint32) []byte { + return BeAppendUint32(b, v) +} func BeUint64(b []byte) uint64 { _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 } +func BEUint64(b []byte) uint64 { + return BeUint64(b) +} func BePutUint64(b []byte, v uint64) { _ = b[7] // early bounds check to guarantee safety of writes below @@ -134,6 +182,9 @@ func BePutUint64(b []byte, v uint64) { b[6] = byte(v >> 8) b[7] = byte(v) } +func BEPutUint64(b []byte, v uint64) { + BePutUint64(b, v) +} func BeAppendUint64(b []byte, v uint64) []byte { return append(b, @@ -147,3 +198,6 @@ func BeAppendUint64(b []byte, v uint64) []byte { byte(v), ) } +func BEAppendUint64(b []byte, v uint64) []byte { + return BeAppendUint64(b, v) +} diff --git a/internal/cpu/cpu.go b/internal/cpu/cpu.go index ed189b5b244..6017b1acc9f 100644 --- a/internal/cpu/cpu.go +++ b/internal/cpu/cpu.go @@ -26,29 +26,30 @@ var CacheLineSize uintptr = CacheLinePadSize // in addition to the cpuid feature bit being set. // The struct is padded to avoid false sharing. var X86 struct { - _ CacheLinePad - HasAES bool - HasADX bool - HasAVX bool - HasAVX2 bool - HasAVX512F bool - HasAVX512BW bool - HasAVX512VL bool - HasBMI1 bool - HasBMI2 bool - HasERMS bool - HasFSRM bool - HasFMA bool - HasOSXSAVE bool - HasPCLMULQDQ bool - HasPOPCNT bool - HasRDTSCP bool - HasSHA bool - HasSSE3 bool - HasSSSE3 bool - HasSSE41 bool - HasSSE42 bool - _ CacheLinePad + _ CacheLinePad + HasAES bool + HasADX bool + HasAVX bool + HasAVX2 bool + HasAVX512F bool + HasAVX512BW bool + HasAVX512VL bool + HasBMI1 bool + HasBMI2 bool + HasERMS bool + HasFSRM bool + HasFMA bool + HasOSXSAVE bool + HasPCLMULQDQ bool + HasPOPCNT bool + HasRDTSCP bool + HasSHA bool + HasSSE3 bool + HasSSSE3 bool + HasSSE41 bool + HasSSE42 bool + HasAVX512VPCLMULQDQ bool + _ CacheLinePad } // The booleans in ARM contain the correspondingly named cpu feature bit. @@ -70,6 +71,7 @@ var ARM64 struct { HasSHA1 bool HasSHA2 bool HasSHA512 bool + HasSHA3 bool HasCRC32 bool HasATOMICS bool HasCPUID bool @@ -81,9 +83,13 @@ var ARM64 struct { // The booleans in Loong64 contain the correspondingly named cpu feature bit. // The struct is padded to avoid false sharing. var Loong64 struct { - _ CacheLinePad - HasCRC32 bool - _ CacheLinePad + _ CacheLinePad + HasLSX bool // support 128-bit vector extension + HasLASX bool // support 256-bit vector extension + HasCRC32 bool // support CRC instruction + HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} + HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction + _ CacheLinePad } var MIPS64X struct { @@ -133,13 +139,27 @@ var S390X struct { _ CacheLinePad } +// RISCV64 contains the supported CPU features and performance characteristics for riscv64 +// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate +// the presence of RISC-V extensions. +// The struct is padded to avoid false sharing. +var RISCV64 struct { + _ CacheLinePad + HasFastMisaligned bool // Fast misaligned accesses + HasV bool // Vector extension compatible with RVV 1.0 + HasZbb bool // Basic bit-manipulation extension + _ CacheLinePad +} + // CPU feature variables are accessed by assembly code in various packages. //go:linkname X86 //go:linkname ARM //go:linkname ARM64 +//go:linkname Loong64 //go:linkname MIPS64X //go:linkname PPC64 //go:linkname S390X +//go:linkname RISCV64 // Initialize examines the processor and sets the relevant variables above. // This is called by the runtime package early in program initialization, @@ -237,7 +257,7 @@ field: // indexByte returns the index of the first instance of c in s, // or -1 if c is not present in s. // indexByte is semantically the same as [strings.IndexByte]. -// We copy this function because "github.com/runZeroInc/excrypto/internal/cpu" should not have external dependencies. +// We copy this function because "internal/cpu" should not have external dependencies. func indexByte(s string, c byte) int { for i := 0; i < len(s); i++ { if s[i] == c { diff --git a/internal/cpu/cpu_arm64.go b/internal/cpu/cpu_arm64.go index 1365991e783..7709966d570 100644 --- a/internal/cpu/cpu_arm64.go +++ b/internal/cpu/cpu_arm64.go @@ -16,6 +16,7 @@ func doinit() { {Name: "sha1", Feature: &ARM64.HasSHA1}, {Name: "sha2", Feature: &ARM64.HasSHA2}, {Name: "sha512", Feature: &ARM64.HasSHA512}, + {Name: "sha3", Feature: &ARM64.HasSHA3}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, {Name: "cpuid", Feature: &ARM64.HasCPUID}, @@ -38,6 +39,7 @@ func extractBits(data uint64, start, end uint) uint { func parseARM64SystemRegisters(isar0, pfr0 uint64) { // ID_AA64ISAR0_EL1 + // https://developer.arm.com/documentation/ddi0601/2025-03/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0 switch extractBits(isar0, 4, 7) { case 1: ARM64.HasAES = true @@ -69,6 +71,11 @@ func parseARM64SystemRegisters(isar0, pfr0 uint64) { ARM64.HasATOMICS = true } + switch extractBits(isar0, 32, 35) { + case 1: + ARM64.HasSHA3 = true + } + switch extractBits(pfr0, 48, 51) { case 1: ARM64.HasDIT = true diff --git a/internal/cpu/cpu_arm64_darwin.go b/internal/cpu/cpu_arm64_darwin.go index 57cf631e891..28b47d60e8a 100644 --- a/internal/cpu/cpu_arm64_darwin.go +++ b/internal/cpu/cpu_arm64_darwin.go @@ -9,15 +9,21 @@ package cpu import _ "unsafe" // for linkname func osInit() { + // macOS 12 moved these to the hw.optional.arm tree, but as of Go 1.24 we + // still support macOS 11. See [Determine Encryption Capabilities]. + // + // [Determine Encryption Capabilities]: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00")) ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00")) ARM64.HasSHA512 = sysctlEnabled([]byte("hw.optional.armv8_2_sha512\x00")) + ARM64.HasSHA3 = sysctlEnabled([]byte("hw.optional.armv8_2_sha3\x00")) + ARM64.HasDIT = sysctlEnabled([]byte("hw.optional.arm.FEAT_DIT\x00")) - // There are no hw.optional sysctl values for the below features on Mac OS 11.0 - // to detect their supported state dynamically. Assume the CPU features that - // Apple Silicon M1 supports to be available as a minimal set of features - // to all Go programs running on darwin/arm64. + // There are no hw.optional sysctl values for the below features on macOS 11 + // to detect their supported state dynamically (although they are available + // in the hw.optional.arm tree on macOS 12). Assume the CPU features that + // Apple Silicon M1 supports to be available on all future iterations. ARM64.HasAES = true ARM64.HasPMULL = true ARM64.HasSHA1 = true diff --git a/internal/cpu/cpu_arm64_hwcap.go b/internal/cpu/cpu_arm64_hwcap.go index cdc1d89c9e4..b6cc1f4d988 100644 --- a/internal/cpu/cpu_arm64_hwcap.go +++ b/internal/cpu/cpu_arm64_hwcap.go @@ -22,6 +22,7 @@ import _ "unsafe" // for linkname var HWCap uint // HWCAP bits. These are exposed by Linux. +// See arch/arm64/include/uapi/asm/hwcap.h. const ( hwcap_AES = 1 << 3 hwcap_PMULL = 1 << 4 @@ -30,18 +31,21 @@ const ( hwcap_CRC32 = 1 << 7 hwcap_ATOMICS = 1 << 8 hwcap_CPUID = 1 << 11 + hwcap_SHA3 = 1 << 17 hwcap_SHA512 = 1 << 21 hwcap_DIT = 1 << 24 ) func hwcapInit(os string) { // HWCap was populated by the runtime from the auxiliary vector. + // See https://docs.kernel.org/arch/arm64/elf_hwcaps.html. // Use HWCap information since reading aarch64 system registers // is not supported in user space on older linux kernels. ARM64.HasAES = isSet(HWCap, hwcap_AES) ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) + ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3) ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512) @@ -67,9 +71,14 @@ func hwcapInit(os string) { // d40 - NeoverseV1 // d49 - NeoverseN2 // d4f - NeoverseV2 - if implementer == 'A' && (part_num == 0xd0c || part_num == 0xd40 || - part_num == 0xd49 || part_num == 0xd4f) { - ARM64.IsNeoverse = true + // d8e - NeoverseN3 + // d84 - NeoverseV3 + // d83 - NeoverseV3ae + if implementer == 'A' { + switch part_num { + case 0xd0c, 0xd40, 0xd49, 0xd4f, 0xd8e, 0xd84, 0xd83: + ARM64.IsNeoverse = true + } } } } diff --git a/internal/cpu/cpu_loong64.go b/internal/cpu/cpu_loong64.go index c4709cc1589..de7eaf0c6c9 100644 --- a/internal/cpu/cpu_loong64.go +++ b/internal/cpu/cpu_loong64.go @@ -10,10 +10,46 @@ package cpu // We choose 64 because Loongson 3A5000 the L1 Dcache is 4-way 256-line 64-byte-per-line. const CacheLinePadSize = 64 +// Bit fields for CPUCFG registers, Related reference documents: +// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg +const ( + // CPUCFG1 bits + cpucfg1_CRC32 = 1 << 25 + + // CPUCFG2 bits + cpucfg2_LAM_BH = 1 << 27 + cpucfg2_LAMCAS = 1 << 28 +) + +// get_cpucfg is implemented in cpu_loong64.s. +func get_cpucfg(reg uint32) uint32 + func doinit() { options = []option{ + {Name: "lsx", Feature: &Loong64.HasLSX}, + {Name: "lasx", Feature: &Loong64.HasLASX}, {Name: "crc32", Feature: &Loong64.HasCRC32}, + {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, + {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, } + // The CPUCFG data on Loong64 only reflects the hardware capabilities, + // not the kernel support status, so features such as LSX and LASX that + // require kernel support cannot be obtained from the CPUCFG data. + // + // These features only require hardware capability support and do not + // require kernel specific support, so they can be obtained directly + // through CPUCFG + cfg1 := get_cpucfg(1) + cfg2 := get_cpucfg(2) + + Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) + Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) + Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) + osInit() } + +func cfgIsSet(cfg uint32, val uint32) bool { + return cfg&val != 0 +} diff --git a/internal/cpu/cpu_loong64.s b/internal/cpu/cpu_loong64.s new file mode 100644 index 00000000000..f02a27803d6 --- /dev/null +++ b/internal/cpu/cpu_loong64.s @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func get_cpucfg(reg uint32) uint32 +TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0-12 + MOVW reg+0(FP), R5 + CPUCFG R5, R4 + MOVW R4, ret+8(FP) + RET diff --git a/internal/cpu/cpu_loong64_hwcap.go b/internal/cpu/cpu_loong64_hwcap.go index b55fde6761e..2b25cc6b4a6 100644 --- a/internal/cpu/cpu_loong64_hwcap.go +++ b/internal/cpu/cpu_loong64_hwcap.go @@ -12,19 +12,17 @@ var HWCap uint // HWCAP bits. These are exposed by the Linux kernel. const ( - hwcap_LOONGARCH_CRC32 = 1 << 6 + hwcap_LOONGARCH_LSX = 1 << 4 + hwcap_LOONGARCH_LASX = 1 << 5 ) func hwcapInit() { - // It is not taken from CPUCFG data regardless of availability of - // CPUCFG, because the CPUCFG data only reflects capabilities of the - // hardware, but not kernel support. - // - // As of 2023, we do not know for sure if the CPUCFG data can be - // patched in software, nor does any known LoongArch kernel do that. - Loong64.HasCRC32 = isSet(HWCap, hwcap_LOONGARCH_CRC32) + // TODO: Features that require kernel support like LSX and LASX can + // be detected here once needed in std library or by the compiler. + Loong64.HasLSX = hwcIsSet(HWCap, hwcap_LOONGARCH_LSX) + Loong64.HasLASX = hwcIsSet(HWCap, hwcap_LOONGARCH_LASX) } -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 +func hwcIsSet(hwc uint, val uint) bool { + return hwc&val != 0 } diff --git a/internal/cpu/cpu_riscv64.go b/internal/cpu/cpu_riscv64.go index 2173fe88860..0fe1704855f 100644 --- a/internal/cpu/cpu_riscv64.go +++ b/internal/cpu/cpu_riscv64.go @@ -6,5 +6,17 @@ package cpu const CacheLinePadSize = 64 +// RISC-V doesn't have a 'cpuid' equivalent. On Linux we rely on the riscv_hwprobe syscall. + func doinit() { + options = []option{ + {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, + {Name: "v", Feature: &RISCV64.HasV}, + {Name: "zbb", Feature: &RISCV64.HasZbb}, + } + osInit() +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 } diff --git a/internal/cpu/cpu_riscv64_linux.go b/internal/cpu/cpu_riscv64_linux.go new file mode 100644 index 00000000000..b67bdf58766 --- /dev/null +++ b/internal/cpu/cpu_riscv64_linux.go @@ -0,0 +1,93 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build riscv64 && linux + +package cpu + +import _ "unsafe" + +// RISC-V extension discovery code for Linux. +// +// A note on detection of the Vector extension using HWCAP. +// +// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. +// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe +// syscall is not available then neither is the Vector extension (which needs kernel support). +// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. +// However, some RISC-V board manufacturers ship boards with an older kernel on top of which +// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe +// patches. These kernels advertise support for the Vector extension using HWCAP. Falling +// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not +// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. +// +// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by +// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board +// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified +// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use +// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector +// extension are binary incompatible. HWCAP can then not be used in isolation to populate the +// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. +// Go will only support the ratified versions >= 1.0 and so any vector code it might generate +// would crash on a Scaleway RV1 instance or a Lichee Pi 4a, if allowed to run. +// +// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector +// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype +// register. This check would allow us to safely detect version 1.0 of the Vector extension +// with HWCAP, if riscv_hwprobe were not available. However, the check cannot +// be added until the assembler supports the Vector instructions. +// +// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the +// extensions it advertises support for are explicitly versioned. It's also worth noting that +// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zvbb. +// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority +// of RISC-V extensions. +// +// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. + +const ( + // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. + riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 + riscv_HWPROBE_IMA_V = 0x4 + riscv_HWPROBE_EXT_ZBB = 0x10 + riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 + riscv_HWPROBE_MISALIGNED_FAST = 0x3 + riscv_HWPROBE_MISALIGNED_MASK = 0x7 +) + +// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. +type riscvHWProbePairs struct { + key int64 + value uint64 +} + +//go:linkname riscvHWProbe +func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool + +func osInit() { + // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key + // field should be initialised with one of the key constants defined above, e.g., + // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. + // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. + + pairs := []riscvHWProbePairs{ + {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, + {riscv_HWPROBE_KEY_CPUPERF_0, 0}, + } + + // This call only indicates that extensions are supported if they are implemented on all cores. + if !riscvHWProbe(pairs, 0) { + return + } + + if pairs[0].key != -1 { + v := uint(pairs[0].value) + RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) + RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) + } + if pairs[1].key != -1 { + v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK + RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST + } +} diff --git a/internal/cpu/cpu_riscv64_other.go b/internal/cpu/cpu_riscv64_other.go new file mode 100644 index 00000000000..1307d822b32 --- /dev/null +++ b/internal/cpu/cpu_riscv64_other.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build riscv64 && !linux + +package cpu + +func osInit() { + // Other operating systems do not support the riscv_hwprobe syscall. +} diff --git a/internal/cpu/cpu_s390x_test.go b/internal/cpu/cpu_s390x_test.go index 999611bce02..4a965c5beea 100644 --- a/internal/cpu/cpu_s390x_test.go +++ b/internal/cpu/cpu_s390x_test.go @@ -6,10 +6,11 @@ package cpu_test import ( "errors" - . "github.com/runZeroInc/excrypto/internal/cpu" "os" "regexp" "testing" + + . "github.com/runZeroInc/excrypto/internal/cpu" ) func getFeatureList() ([]string, error) { diff --git a/internal/cpu/cpu_test.go b/internal/cpu/cpu_test.go index 516df07e014..c46c9c0ea9b 100644 --- a/internal/cpu/cpu_test.go +++ b/internal/cpu/cpu_test.go @@ -5,12 +5,12 @@ package cpu_test import ( + "os/exec" + "testing" + . "github.com/runZeroInc/excrypto/internal/cpu" "github.com/runZeroInc/excrypto/internal/godebug" "github.com/runZeroInc/excrypto/internal/testenv" - "os" - "os/exec" - "testing" ) func MustHaveDebugOptionsSupport(t *testing.T) { @@ -26,11 +26,9 @@ func MustSupportFeatureDetection(t *testing.T) { func runDebugOptionsTest(t *testing.T, test string, options string) { MustHaveDebugOptionsSupport(t) - testenv.MustHaveExec(t) - env := "GODEBUG=" + options - cmd := exec.Command(os.Args[0], "-test.run=^"+test+"$") + cmd := exec.Command(testenv.Executable(t), "-test.run=^"+test+"$") cmd.Env = append(cmd.Env, env) output, err := cmd.CombinedOutput() diff --git a/internal/cpu/cpu_x86.go b/internal/cpu/cpu_x86.go index ee812076e96..69b9542ae2a 100644 --- a/internal/cpu/cpu_x86.go +++ b/internal/cpu/cpu_x86.go @@ -40,6 +40,10 @@ const ( cpuid_SHA = 1 << 29 cpuid_AVX512BW = 1 << 30 cpuid_AVX512VL = 1 << 31 + + // ecx bits + cpuid_AVX512VPCLMULQDQ = 1 << 10 + // edx bits cpuid_FSRM = 1 << 4 // edx bits for CPUID 0x80000001 @@ -57,6 +61,7 @@ func doinit() { {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, {Name: "rdtscp", Feature: &X86.HasRDTSCP}, {Name: "sha", Feature: &X86.HasSHA}, + {Name: "vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, } level := getGOAMD64level() if level < 2 { @@ -139,7 +144,7 @@ func doinit() { return } - _, ebx7, _, edx7 := cpuid(7, 0) + _, ebx7, ecx7, edx7 := cpuid(7, 0) X86.HasBMI1 = isSet(ebx7, cpuid_BMI1) X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) @@ -151,6 +156,7 @@ func doinit() { if X86.HasAVX512F { X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) + X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) } X86.HasFSRM = isSet(edx7, cpuid_FSRM) diff --git a/internal/cpu/cpu_x86_test.go b/internal/cpu/cpu_x86_test.go index a22fcb731a0..bfafbc7372d 100644 --- a/internal/cpu/cpu_x86_test.go +++ b/internal/cpu/cpu_x86_test.go @@ -7,9 +7,10 @@ package cpu_test import ( + "testing" + . "github.com/runZeroInc/excrypto/internal/cpu" "github.com/runZeroInc/excrypto/internal/godebug" - "testing" ) func TestX86ifAVX2hasAVX(t *testing.T) { diff --git a/internal/godebugs/table.go b/internal/godebugs/table.go index 2de29dc6c80..2d008825459 100644 --- a/internal/godebugs/table.go +++ b/internal/godebugs/table.go @@ -9,11 +9,12 @@ package godebugs // An Info describes a single known GODEBUG setting. type Info struct { - Name string // name of the setting ("panicnil") - Package string // package that uses the setting ("runtime") - Changed int // minor version when default changed, if any; 21 means Go 1.21 - Old string // value that restores behavior prior to Changed - Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault] + Name string // name of the setting ("panicnil") + Package string // package that uses the setting ("runtime") + Changed int // minor version when default changed, if any; 21 means Go 1.21 + Old string // value that restores behavior prior to Changed + Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault] + Immutable bool // setting cannot be changed after program start } // All is the table of known settings, sorted by Name. @@ -25,11 +26,18 @@ type Info struct { // Note: After adding entries to this table, update the list in doc/godebug.md as well. // (Otherwise the test in this package will fail.) var All = []Info{ + {Name: "allowmultiplevcs", Package: "cmd/go"}, {Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1"}, + {Name: "containermaxprocs", Package: "runtime", Changed: 25, Old: "0"}, + {Name: "dataindependenttiming", Package: "crypto/subtle", Opaque: true}, + {Name: "decoratemappings", Package: "runtime", Opaque: true, Changed: 25, Old: "0"}, + {Name: "embedfollowsymlinks", Package: "cmd/go"}, {Name: "execerrdot", Package: "os/exec"}, - {Name: "gocachehash", Package: "github.com/runZeroInc/excrypto/cmd/go"}, - {Name: "gocachetest", Package: "github.com/runZeroInc/excrypto/cmd/go"}, - {Name: "gocacheverify", Package: "github.com/runZeroInc/excrypto/cmd/go"}, + {Name: "fips140", Package: "crypto/fips140", Opaque: true, Immutable: true}, + {Name: "gocachehash", Package: "cmd/go"}, + {Name: "gocachetest", Package: "cmd/go"}, + {Name: "gocacheverify", Package: "cmd/go"}, + {Name: "gotestjsonbuildtext", Package: "cmd/go", Changed: 24, Old: "1"}, {Name: "gotypesalias", Package: "go/types", Changed: 23, Old: "0"}, {Name: "http2client", Package: "net/http"}, {Name: "http2debug", Package: "net/http", Opaque: true}, @@ -48,20 +56,24 @@ var All = []Info{ {Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"}, {Name: "randautoseed", Package: "math/rand"}, {Name: "randseednop", Package: "math/rand", Changed: 24, Old: "0"}, + {Name: "rsa1024min", Package: "crypto/rsa", Changed: 24, Old: "0"}, {Name: "tarinsecurepath", Package: "archive/tar"}, - {Name: "tls10server", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 22, Old: "1"}, - {Name: "tls3des", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 23, Old: "1"}, - {Name: "tlskyber", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 23, Old: "0", Opaque: true}, - {Name: "tlsmaxrsasize", Package: "github.com/runZeroInc/excrypto/crypto/tls"}, - {Name: "tlsrsakex", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 22, Old: "1"}, - {Name: "tlsunsafeekm", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 22, Old: "1"}, - {Name: "winreadlinkvolume", Package: "os", Changed: 22, Old: "0"}, - {Name: "winsymlink", Package: "os", Changed: 22, Old: "0"}, - {Name: "x509keypairleaf", Package: "github.com/runZeroInc/excrypto/crypto/tls", Changed: 23, Old: "0"}, - {Name: "x509negativeserial", Package: "github.com/runZeroInc/excrypto/crypto/x509", Changed: 23, Old: "1"}, - {Name: "x509sha1", Package: "github.com/runZeroInc/excrypto/crypto/x509"}, - {Name: "x509usefallbackroots", Package: "github.com/runZeroInc/excrypto/crypto/x509"}, - {Name: "x509usepolicies", Package: "github.com/runZeroInc/excrypto/crypto/x509"}, + {Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"}, + {Name: "tls3des", Package: "crypto/tls", Changed: 23, Old: "1"}, + {Name: "tlsmaxrsasize", Package: "crypto/tls"}, + {Name: "tlsmlkem", Package: "crypto/tls", Changed: 24, Old: "0", Opaque: true}, + {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"}, + {Name: "tlssha1", Package: "crypto/tls", Changed: 25, Old: "1"}, + {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"}, + {Name: "updatemaxprocs", Package: "runtime", Changed: 25, Old: "0"}, + {Name: "winreadlinkvolume", Package: "os", Changed: 23, Old: "0"}, + {Name: "winsymlink", Package: "os", Changed: 23, Old: "0"}, + {Name: "x509keypairleaf", Package: "crypto/tls", Changed: 23, Old: "0"}, + {Name: "x509negativeserial", Package: "crypto/x509", Changed: 23, Old: "1"}, + {Name: "x509rsacrt", Package: "crypto/x509", Changed: 24, Old: "0"}, + {Name: "x509sha256skid", Package: "crypto/x509", Changed: 25, Old: "0"}, + {Name: "x509usefallbackroots", Package: "crypto/x509"}, + {Name: "x509usepolicies", Package: "crypto/x509", Changed: 24, Old: "0"}, {Name: "zipinsecurepath", Package: "archive/zip"}, } diff --git a/internal/obscuretestdata/obscuretestdata.go b/internal/obscuretestdata/obscuretestdata.go new file mode 100644 index 00000000000..d54d3f68c2a --- /dev/null +++ b/internal/obscuretestdata/obscuretestdata.go @@ -0,0 +1,65 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package obscuretestdata contains functionality used by tests to more easily +// work with testdata that must be obscured primarily due to +// golang.org/issue/34986. +package obscuretestdata + +import ( + "encoding/base64" + "io" + "os" +) + +// Rot13 returns the rot13 encoding or decoding of its input. +func Rot13(data []byte) []byte { + out := make([]byte, len(data)) + copy(out, data) + for i, c := range out { + switch { + case 'A' <= c && c <= 'M' || 'a' <= c && c <= 'm': + out[i] = c + 13 + case 'N' <= c && c <= 'Z' || 'n' <= c && c <= 'z': + out[i] = c - 13 + } + } + return out +} + +// DecodeToTempFile decodes the named file to a temporary location. +// If successful, it returns the path of the decoded file. +// The caller is responsible for ensuring that the temporary file is removed. +func DecodeToTempFile(name string) (path string, err error) { + f, err := os.Open(name) + if err != nil { + return "", err + } + defer f.Close() + + tmp, err := os.CreateTemp("", "obscuretestdata-decoded-") + if err != nil { + return "", err + } + if _, err := io.Copy(tmp, base64.NewDecoder(base64.StdEncoding, f)); err != nil { + tmp.Close() + os.Remove(tmp.Name()) + return "", err + } + if err := tmp.Close(); err != nil { + os.Remove(tmp.Name()) + return "", err + } + return tmp.Name(), nil +} + +// ReadFile reads the named file and returns its decoded contents. +func ReadFile(name string) ([]byte, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + return io.ReadAll(base64.NewDecoder(base64.StdEncoding, f)) +} diff --git a/refs/crypto.hash b/refs/crypto.hash index 8f8f12805e6..333a7dd6ed4 100644 --- a/refs/crypto.hash +++ b/refs/crypto.hash @@ -1 +1 @@ -8e478de4e6c91a0de763cf2e308f7598677f5c58 +d524e1eccd559b40130c3bac77f3f7dc33d476ab diff --git a/refs/xcrypto.hash b/refs/xcrypto.hash index 771b39f664e..c298b4a619d 100644 --- a/refs/xcrypto.hash +++ b/refs/xcrypto.hash @@ -1 +1 @@ -911360c8a4f464342b9fe7c23632be57fca87b20 +d0a798f774735c176ed0d3500ac986957a02660f diff --git a/x/crypto/argon2/_asm/go.mod b/x/crypto/argon2/_asm/go.mod index 52b11c990d4..da255d3d327 100644 --- a/x/crypto/argon2/_asm/go.mod +++ b/x/crypto/argon2/_asm/go.mod @@ -1,6 +1,6 @@ module argon2/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/argon2/blake2b.go b/x/crypto/argon2/blake2b.go index 3b76bb9d899..8967f5b3060 100644 --- a/x/crypto/argon2/blake2b.go +++ b/x/crypto/argon2/blake2b.go @@ -6,7 +6,8 @@ package argon2 import ( "encoding/binary" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/x/crypto/blake2b" ) diff --git a/x/crypto/bcrypt/bcrypt.go b/x/crypto/bcrypt/bcrypt.go index 80e3549d1a1..3e2e24ff60d 100644 --- a/x/crypto/bcrypt/bcrypt.go +++ b/x/crypto/bcrypt/bcrypt.go @@ -8,12 +8,13 @@ package bcrypt // The code is a port of Provos and Mazières's C implementation. import ( - "crypto/rand" "errors" "fmt" "io" "strconv" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/subtle" "github.com/runZeroInc/excrypto/x/crypto/blowfish" ) diff --git a/x/crypto/blake2b/_asm/AVX2/go.mod b/x/crypto/blake2b/_asm/AVX2/go.mod index 6b353a4653e..4cc4694aef8 100644 --- a/x/crypto/blake2b/_asm/AVX2/go.mod +++ b/x/crypto/blake2b/_asm/AVX2/go.mod @@ -1,11 +1,10 @@ module blake2b/_asm/AVX2 -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 github.com/runZeroInc/excrypto/x/crypto v0.33.0 - ) require ( diff --git a/x/crypto/blake2b/_asm/standard/go.mod b/x/crypto/blake2b/_asm/standard/go.mod index dac14454fbd..5cfe858b51a 100644 --- a/x/crypto/blake2b/_asm/standard/go.mod +++ b/x/crypto/blake2b/_asm/standard/go.mod @@ -1,6 +1,6 @@ module blake2b/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/blake2b/blake2b.go b/x/crypto/blake2b/blake2b.go index d2e98d4295b..324a07b1cea 100644 --- a/x/crypto/blake2b/blake2b.go +++ b/x/crypto/blake2b/blake2b.go @@ -21,7 +21,8 @@ package blake2b import ( "encoding/binary" "errors" - "hash" + + "github.com/runZeroInc/excrypto/hash" ) const ( diff --git a/x/crypto/blake2b/blake2b_test.go b/x/crypto/blake2b/blake2b_test.go index 723327ab563..7c2b2b44fb0 100644 --- a/x/crypto/blake2b/blake2b_test.go +++ b/x/crypto/blake2b/blake2b_test.go @@ -9,9 +9,10 @@ import ( "encoding" "encoding/hex" "fmt" - "hash" "io" "testing" + + "github.com/runZeroInc/excrypto/hash" ) func fromHex(s string) []byte { diff --git a/x/crypto/blake2b/register.go b/x/crypto/blake2b/register.go index 095d25f8ade..c0dddd02340 100644 --- a/x/crypto/blake2b/register.go +++ b/x/crypto/blake2b/register.go @@ -5,7 +5,7 @@ package blake2b import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/blake2s/_asm/go.mod b/x/crypto/blake2s/_asm/go.mod index 2f46b8223f3..95cc369b8d7 100644 --- a/x/crypto/blake2s/_asm/go.mod +++ b/x/crypto/blake2s/_asm/go.mod @@ -1,6 +1,6 @@ module blake2s/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/blake2s/blake2s.go b/x/crypto/blake2s/blake2s.go index b775ee7296d..6e4182d6796 100644 --- a/x/crypto/blake2s/blake2s.go +++ b/x/crypto/blake2s/blake2s.go @@ -21,7 +21,8 @@ package blake2s import ( "encoding/binary" "errors" - "hash" + + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/bn256/bn256.go b/x/crypto/bn256/bn256.go index 66616875513..980f42d2348 100644 --- a/x/crypto/bn256/bn256.go +++ b/x/crypto/bn256/bn256.go @@ -26,9 +26,10 @@ package bn256 import ( - "crypto/rand" "io" "math/big" + + "crypto/rand" ) // G1 is an abstract cyclic group. The zero value is suitable for use as the diff --git a/x/crypto/bn256/bn256_test.go b/x/crypto/bn256/bn256_test.go index 1cec3884ecd..daee86b5555 100644 --- a/x/crypto/bn256/bn256_test.go +++ b/x/crypto/bn256/bn256_test.go @@ -6,9 +6,10 @@ package bn256 import ( "bytes" - "crypto/rand" "math/big" "testing" + + "crypto/rand" ) func TestGFp2Invert(t *testing.T) { diff --git a/x/crypto/chacha20poly1305/_asm/go.mod b/x/crypto/chacha20poly1305/_asm/go.mod index 5d28beeff32..487a6bb3a71 100644 --- a/x/crypto/chacha20poly1305/_asm/go.mod +++ b/x/crypto/chacha20poly1305/_asm/go.mod @@ -1,6 +1,6 @@ module chacha20poly1305/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/cryptobyte/asn1.go b/x/crypto/cryptobyte/asn1.go index af682bca8ef..446aa8110f0 100644 --- a/x/crypto/cryptobyte/asn1.go +++ b/x/crypto/cryptobyte/asn1.go @@ -234,7 +234,7 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { // Identifiers with the low five bits set indicate high-tag-number format // (two or more octets), which we don't support. if tag&0x1f == 0x1f { - b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) + b.err = fmt.Errorf("cryptobyte: high-tag number identifier octets not supported: 0x%x", tag) return } b.AddUint8(uint8(tag)) diff --git a/x/crypto/curve25519/curve25519.go b/x/crypto/curve25519/curve25519.go index 21ca3b2ee4b..fe57c0c8970 100644 --- a/x/crypto/curve25519/curve25519.go +++ b/x/crypto/curve25519/curve25519.go @@ -10,7 +10,7 @@ // in the crypto/ecdh package. package curve25519 -import "crypto/ecdh" +import "github.com/runZeroInc/excrypto/crypto/ecdh" // ScalarMult sets dst to the product scalar * point. // diff --git a/x/crypto/curve25519/curve25519_test.go b/x/crypto/curve25519/curve25519_test.go index 87d12c879c7..79318a49e57 100644 --- a/x/crypto/curve25519/curve25519_test.go +++ b/x/crypto/curve25519/curve25519_test.go @@ -6,10 +6,11 @@ package curve25519_test import ( "bytes" - "crypto/rand" "encoding/hex" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/curve25519" ) diff --git a/x/crypto/hkdf/example_test.go b/x/crypto/hkdf/example_test.go index c27a039401e..771c99bcc4e 100644 --- a/x/crypto/hkdf/example_test.go +++ b/x/crypto/hkdf/example_test.go @@ -6,10 +6,11 @@ package hkdf_test import ( "bytes" - "crypto/rand" "fmt" "io" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/x/crypto/hkdf" ) diff --git a/x/crypto/hkdf/hkdf.go b/x/crypto/hkdf/hkdf.go index 0721b358965..f0e5769ce4b 100644 --- a/x/crypto/hkdf/hkdf.go +++ b/x/crypto/hkdf/hkdf.go @@ -12,9 +12,10 @@ package hkdf import ( "errors" - "hash" "io" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/hmac" ) diff --git a/x/crypto/hkdf/hkdf_test.go b/x/crypto/hkdf/hkdf_test.go index 9f2259ac2ee..993d64fbcab 100644 --- a/x/crypto/hkdf/hkdf_test.go +++ b/x/crypto/hkdf/hkdf_test.go @@ -5,10 +5,11 @@ package hkdf import ( "bytes" - "hash" "io" "testing" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/md5" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" diff --git a/x/crypto/internal/poly1305/_asm/go.mod b/x/crypto/internal/poly1305/_asm/go.mod index 26189ffb1bd..54f50966840 100644 --- a/x/crypto/internal/poly1305/_asm/go.mod +++ b/x/crypto/internal/poly1305/_asm/go.mod @@ -1,6 +1,6 @@ module internal/poly1305/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/internal/poly1305/mac_noasm.go b/x/crypto/internal/poly1305/mac_noasm.go index bd896bdc76d..8d99551feec 100644 --- a/x/crypto/internal/poly1305/mac_noasm.go +++ b/x/crypto/internal/poly1305/mac_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!amd64 && !ppc64le && !ppc64 && !s390x) || !gc || purego +//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego package poly1305 diff --git a/x/crypto/internal/poly1305/poly1305_test.go b/x/crypto/internal/poly1305/poly1305_test.go index e7ec6d19dd2..3b72f59d5ea 100644 --- a/x/crypto/internal/poly1305/poly1305_test.go +++ b/x/crypto/internal/poly1305/poly1305_test.go @@ -5,12 +5,13 @@ package poly1305 import ( - "crypto/rand" "encoding/binary" "encoding/hex" "flag" "testing" "unsafe" + + "crypto/rand" ) var stressFlag = flag.Bool("stress", false, "run slow stress tests") diff --git a/x/crypto/internal/poly1305/sum_amd64.go b/x/crypto/internal/poly1305/sum_asm.go similarity index 94% rename from x/crypto/internal/poly1305/sum_amd64.go rename to x/crypto/internal/poly1305/sum_asm.go index 164cd47d322..315b84ac39b 100644 --- a/x/crypto/internal/poly1305/sum_amd64.go +++ b/x/crypto/internal/poly1305/sum_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego +//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le) package poly1305 diff --git a/x/crypto/internal/poly1305/sum_loong64.s b/x/crypto/internal/poly1305/sum_loong64.s new file mode 100644 index 00000000000..bc8361da402 --- /dev/null +++ b/x/crypto/internal/poly1305/sum_loong64.s @@ -0,0 +1,123 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVV state+0(FP), R4 + MOVV msg_base+8(FP), R5 + MOVV msg_len+16(FP), R6 + + MOVV $0x10, R7 + + MOVV (R4), R8 // h0 + MOVV 8(R4), R9 // h1 + MOVV 16(R4), R10 // h2 + MOVV 24(R4), R11 // r0 + MOVV 32(R4), R12 // r1 + + BLT R6, R7, bytes_between_0_and_15 + +loop: + MOVV (R5), R14 // msg[0:8] + MOVV 8(R5), R16 // msg[8:16] + ADDV R14, R8, R8 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow) + ADDV R16, R9, R27 + SGTU R14, R8, R24 // h0.carry + SGTU R9, R27, R28 + ADDV R27, R24, R9 // h1 + SGTU R27, R9, R24 + OR R24, R28, R24 // h1.carry + ADDV $0x01, R24, R24 + ADDV R10, R24, R10 // h2 + + ADDV $16, R5, R5 // msg = msg[16:] + +multiply: + MULV R8, R11, R14 // h0r0.lo + MULHVU R8, R11, R15 // h0r0.hi + MULV R9, R11, R13 // h1r0.lo + MULHVU R9, R11, R16 // h1r0.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MULV R10, R11, R25 + ADDV R16, R25, R25 + MULV R8, R12, R13 // h0r1.lo + MULHVU R8, R12, R16 // h0r1.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MOVV R16, R8 + MULV R10, R12, R26 // h2r1 + MULV R9, R12, R13 // h1r1.lo + MULHVU R9, R12, R16 // h1r1.hi + ADDV R13, R25, R25 + ADDV R16, R26, R27 + SGTU R13, R25, R24 + ADDV R27, R24, R26 + ADDV R8, R25, R25 + SGTU R8, R25, R24 + ADDV R24, R26, R26 + AND $3, R25, R10 + AND $-4, R25, R17 + ADDV R17, R14, R8 + ADDV R26, R15, R27 + SGTU R17, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + SLLV $62, R26, R27 + SRLV $2, R25, R28 + SRLV $2, R26, R26 + OR R27, R28, R25 + ADDV R25, R8, R8 + ADDV R26, R9, R27 + SGTU R25, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + + SUBV $16, R6, R6 + BGE R6, R7, loop + +bytes_between_0_and_15: + BEQ R6, R0, done + MOVV $1, R14 + XOR R15, R15 + ADDV R6, R5, R5 + +flush_buffer: + MOVBU -1(R5), R25 + SRLV $56, R14, R24 + SLLV $8, R15, R28 + SLLV $8, R14, R14 + OR R24, R28, R15 + XOR R25, R14, R14 + SUBV $1, R6, R6 + SUBV $1, R5, R5 + BNE R6, R0, flush_buffer + + ADDV R14, R8, R8 + SGTU R14, R8, R24 + ADDV R15, R9, R27 + SGTU R15, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R10, R24, R10 + + MOVV $16, R6 + JMP multiply + +done: + MOVV R8, (R4) + MOVV R9, 8(R4) + MOVV R10, 16(R4) + RET diff --git a/x/crypto/internal/poly1305/sum_ppc64x.go b/x/crypto/internal/poly1305/sum_ppc64x.go deleted file mode 100644 index 1a1679aaad9..00000000000 --- a/x/crypto/internal/poly1305/sum_ppc64x.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc && !purego && (ppc64 || ppc64le) - -package poly1305 - -//go:noescape -func update(state *macState, msg []byte) - -// mac is a wrapper for macGeneric that redirects calls that would have gone to -// updateGeneric to update. -// -// Its Write and Sum methods are otherwise identical to the macGeneric ones, but -// using function pointers would carry a major performance cost. -type mac struct{ macGeneric } - -func (h *mac) Write(p []byte) (int, error) { - nn := len(p) - if h.offset > 0 { - n := copy(h.buffer[h.offset:], p) - if h.offset+n < TagSize { - h.offset += n - return nn, nil - } - p = p[n:] - h.offset = 0 - update(&h.macState, h.buffer[:]) - } - if n := len(p) - (len(p) % TagSize); n > 0 { - update(&h.macState, p[:n]) - p = p[n:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return nn, nil -} - -func (h *mac) Sum(out *[16]byte) { - state := h.macState - if h.offset > 0 { - update(&state, h.buffer[:h.offset]) - } - finalize(out, &state.h, &state.s) -} diff --git a/x/crypto/internal/wycheproof/ecdh_stdlib_test.go b/x/crypto/internal/wycheproof/ecdh_stdlib_test.go index 24a83e245b7..07bed40d70a 100644 --- a/x/crypto/internal/wycheproof/ecdh_stdlib_test.go +++ b/x/crypto/internal/wycheproof/ecdh_stdlib_test.go @@ -6,9 +6,10 @@ package wycheproof import ( "bytes" - "crypto/ecdh" "fmt" "testing" + + "github.com/runZeroInc/excrypto/crypto/ecdh" ) func TestECDHStdLib(t *testing.T) { diff --git a/x/crypto/md4/md4.go b/x/crypto/md4/md4.go index af84761526c..b85e26be826 100644 --- a/x/crypto/md4/md4.go +++ b/x/crypto/md4/md4.go @@ -10,7 +10,7 @@ package md4 import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/nacl/box/box_test.go b/x/crypto/nacl/box/box_test.go index 3a052249c85..ba3f4235304 100644 --- a/x/crypto/nacl/box/box_test.go +++ b/x/crypto/nacl/box/box_test.go @@ -6,10 +6,11 @@ package box import ( "bytes" - "crypto/rand" "encoding/hex" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/curve25519" ) diff --git a/x/crypto/nacl/secretbox/example_test.go b/x/crypto/nacl/secretbox/example_test.go index d99dbd654d6..f8962bbbbc1 100644 --- a/x/crypto/nacl/secretbox/example_test.go +++ b/x/crypto/nacl/secretbox/example_test.go @@ -5,11 +5,12 @@ package secretbox_test import ( - "crypto/rand" "encoding/hex" "fmt" "io" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/nacl/secretbox" ) diff --git a/x/crypto/nacl/secretbox/secretbox_test.go b/x/crypto/nacl/secretbox/secretbox_test.go index 3c70b0f4b3d..e2db7a4c1c2 100644 --- a/x/crypto/nacl/secretbox/secretbox_test.go +++ b/x/crypto/nacl/secretbox/secretbox_test.go @@ -6,9 +6,10 @@ package secretbox import ( "bytes" - "crypto/rand" "encoding/hex" "testing" + + "crypto/rand" ) func TestSealOpen(t *testing.T) { diff --git a/x/crypto/nacl/sign/sign_test.go b/x/crypto/nacl/sign/sign_test.go index db269014c2b..82d7191b967 100644 --- a/x/crypto/nacl/sign/sign_test.go +++ b/x/crypto/nacl/sign/sign_test.go @@ -6,9 +6,10 @@ package sign import ( "bytes" - "crypto/rand" "encoding/hex" "testing" + + "crypto/rand" ) var testSignedMessage, _ = hex.DecodeString("26a0a47f733d02ddb74589b6cbd6f64a7dab1947db79395a1a9e00e4c902c0f185b119897b89b248d16bab4ea781b5a3798d25c2984aec833dddab57e0891e0d68656c6c6f20776f726c64") diff --git a/x/crypto/ocsp/ocsp.go b/x/crypto/ocsp/ocsp.go index dca1234d742..7a03f1f3056 100644 --- a/x/crypto/ocsp/ocsp.go +++ b/x/crypto/ocsp/ocsp.go @@ -8,13 +8,14 @@ package ocsp import ( - "crypto/rand" "errors" "fmt" "math/big" "strconv" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" diff --git a/x/crypto/ocsp/ocsp_test.go b/x/crypto/ocsp/ocsp_test.go index 3c3b7b1efc9..f96351761aa 100644 --- a/x/crypto/ocsp/ocsp_test.go +++ b/x/crypto/ocsp/ocsp_test.go @@ -6,7 +6,6 @@ package ocsp import ( "bytes" - "crypto/rand" "encoding/hex" "encoding/pem" "math/big" @@ -14,6 +13,8 @@ import ( "testing" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/crypto/sha1" diff --git a/x/crypto/openpgp/canonical_text.go b/x/crypto/openpgp/canonical_text.go index e601e389f12..081d4702e4c 100644 --- a/x/crypto/openpgp/canonical_text.go +++ b/x/crypto/openpgp/canonical_text.go @@ -4,7 +4,7 @@ package openpgp -import "hash" +import "github.com/runZeroInc/excrypto/hash" // NewCanonicalTextHash reformats text written to it into the canonical // form and then applies the hash h. See RFC 4880, section 5.2.1. diff --git a/x/crypto/openpgp/clearsign/clearsign.go b/x/crypto/openpgp/clearsign/clearsign.go index 13a12f51f20..729ab70daca 100644 --- a/x/crypto/openpgp/clearsign/clearsign.go +++ b/x/crypto/openpgp/clearsign/clearsign.go @@ -19,12 +19,13 @@ import ( "bufio" "bytes" "fmt" - "hash" "io" "net/textproto" "strconv" "strings" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/x/crypto/openpgp/armor" "github.com/runZeroInc/excrypto/x/crypto/openpgp/errors" diff --git a/x/crypto/openpgp/elgamal/elgamal.go b/x/crypto/openpgp/elgamal/elgamal.go index f94131a4531..96d9d90c577 100644 --- a/x/crypto/openpgp/elgamal/elgamal.go +++ b/x/crypto/openpgp/elgamal/elgamal.go @@ -19,11 +19,12 @@ package elgamal import ( - "crypto/rand" "errors" "io" "math/big" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/subtle" ) diff --git a/x/crypto/openpgp/elgamal/elgamal_test.go b/x/crypto/openpgp/elgamal/elgamal_test.go index 9f0a8547c3e..03d7ce83a6d 100644 --- a/x/crypto/openpgp/elgamal/elgamal_test.go +++ b/x/crypto/openpgp/elgamal/elgamal_test.go @@ -6,9 +6,10 @@ package elgamal import ( "bytes" - "crypto/rand" "math/big" "testing" + + "crypto/rand" ) // This is the 1024-bit MODP group from RFC 5114, section 2.1: diff --git a/x/crypto/openpgp/packet/config.go b/x/crypto/openpgp/packet/config.go index 693e9262cf5..5ab985380fc 100644 --- a/x/crypto/openpgp/packet/config.go +++ b/x/crypto/openpgp/packet/config.go @@ -5,10 +5,11 @@ package packet import ( - "crypto/rand" "io" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/openpgp/packet/ocfb_test.go b/x/crypto/openpgp/packet/ocfb_test.go index 375800b7d06..e084bbbe2ac 100644 --- a/x/crypto/openpgp/packet/ocfb_test.go +++ b/x/crypto/openpgp/packet/ocfb_test.go @@ -6,9 +6,10 @@ package packet import ( "bytes" - "crypto/rand" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/aes" ) diff --git a/x/crypto/openpgp/packet/private_key_test.go b/x/crypto/openpgp/packet/private_key_test.go index 76cf6273713..032d4c04d08 100644 --- a/x/crypto/openpgp/packet/private_key_test.go +++ b/x/crypto/openpgp/packet/private_key_test.go @@ -8,10 +8,11 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "hash" "testing" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" diff --git a/x/crypto/openpgp/packet/public_key.go b/x/crypto/openpgp/packet/public_key.go index dca8b1252d0..fbbcacec695 100644 --- a/x/crypto/openpgp/packet/public_key.go +++ b/x/crypto/openpgp/packet/public_key.go @@ -8,12 +8,13 @@ import ( "bytes" "encoding/binary" "fmt" - "hash" "io" "math/big" "strconv" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdsa" diff --git a/x/crypto/openpgp/packet/public_key_v3.go b/x/crypto/openpgp/packet/public_key_v3.go index 35541855a6d..d92e1044749 100644 --- a/x/crypto/openpgp/packet/public_key_v3.go +++ b/x/crypto/openpgp/packet/public_key_v3.go @@ -7,12 +7,13 @@ package packet import ( "encoding/binary" "fmt" - "hash" "io" "math/big" "strconv" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/md5" "github.com/runZeroInc/excrypto/crypto/rsa" diff --git a/x/crypto/openpgp/packet/signature.go b/x/crypto/openpgp/packet/signature.go index d63ab720e39..9ca39ebf86d 100644 --- a/x/crypto/openpgp/packet/signature.go +++ b/x/crypto/openpgp/packet/signature.go @@ -7,12 +7,13 @@ package packet import ( "bytes" "encoding/binary" - "hash" "io" "math/big" "strconv" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdsa" diff --git a/x/crypto/openpgp/packet/symmetrically_encrypted.go b/x/crypto/openpgp/packet/symmetrically_encrypted.go index f14ffde5985..4ff37ab0cf8 100644 --- a/x/crypto/openpgp/packet/symmetrically_encrypted.go +++ b/x/crypto/openpgp/packet/symmetrically_encrypted.go @@ -5,10 +5,11 @@ package packet import ( - "hash" "io" "strconv" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/subtle" diff --git a/x/crypto/openpgp/read.go b/x/crypto/openpgp/read.go index 7665f348742..f2d0651d006 100644 --- a/x/crypto/openpgp/read.go +++ b/x/crypto/openpgp/read.go @@ -12,10 +12,11 @@ package openpgp import ( - "hash" "io" "strconv" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" _ "github.com/runZeroInc/excrypto/crypto/sha256" "github.com/runZeroInc/excrypto/x/crypto/openpgp/armor" diff --git a/x/crypto/openpgp/s2k/s2k.go b/x/crypto/openpgp/s2k/s2k.go index d8878e1914d..5c0ee44b96c 100644 --- a/x/crypto/openpgp/s2k/s2k.go +++ b/x/crypto/openpgp/s2k/s2k.go @@ -13,10 +13,11 @@ package s2k import ( - "hash" "io" "strconv" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/x/crypto/openpgp/errors" ) diff --git a/x/crypto/openpgp/s2k/s2k_test.go b/x/crypto/openpgp/s2k/s2k_test.go index f9f1e614c26..c0ce0e0deae 100644 --- a/x/crypto/openpgp/s2k/s2k_test.go +++ b/x/crypto/openpgp/s2k/s2k_test.go @@ -6,10 +6,11 @@ package s2k import ( "bytes" - "crypto/rand" "encoding/hex" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" _ "github.com/runZeroInc/excrypto/crypto/md5" "github.com/runZeroInc/excrypto/crypto/sha1" diff --git a/x/crypto/openpgp/write.go b/x/crypto/openpgp/write.go index 82b90119637..a3ba46ca88b 100644 --- a/x/crypto/openpgp/write.go +++ b/x/crypto/openpgp/write.go @@ -5,11 +5,12 @@ package openpgp import ( - "hash" "io" "strconv" "time" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/x/crypto/openpgp/armor" "github.com/runZeroInc/excrypto/x/crypto/openpgp/errors" diff --git a/x/crypto/otr/otr.go b/x/crypto/otr/otr.go index a1ff439ed6c..f4dbda5ce2a 100644 --- a/x/crypto/otr/otr.go +++ b/x/crypto/otr/otr.go @@ -12,15 +12,17 @@ package otr import ( "bytes" - "crypto/rand" "encoding/base64" "encoding/hex" "errors" - "hash" "io" "math/big" "strconv" + "github.com/runZeroInc/excrypto/hash" + + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/dsa" diff --git a/x/crypto/otr/otr_test.go b/x/crypto/otr/otr_test.go index cfcd062b274..1c17d69ecd2 100644 --- a/x/crypto/otr/otr_test.go +++ b/x/crypto/otr/otr_test.go @@ -7,12 +7,13 @@ package otr import ( "bufio" "bytes" - "crypto/rand" "encoding/hex" "math/big" "os" "os/exec" "testing" + + "crypto/rand" ) var isQueryTests = []struct { diff --git a/x/crypto/otr/smp.go b/x/crypto/otr/smp.go index 1b1d4f1abdb..eb50fa2ac6a 100644 --- a/x/crypto/otr/smp.go +++ b/x/crypto/otr/smp.go @@ -12,9 +12,10 @@ package otr import ( "bytes" "errors" - "hash" "math/big" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/sha256" ) diff --git a/x/crypto/pbkdf2/pbkdf2.go b/x/crypto/pbkdf2/pbkdf2.go index 72ea73a8db8..674a1980902 100644 --- a/x/crypto/pbkdf2/pbkdf2.go +++ b/x/crypto/pbkdf2/pbkdf2.go @@ -19,7 +19,7 @@ pbkdf2.Key. package pbkdf2 import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto/hmac" ) diff --git a/x/crypto/pbkdf2/pbkdf2_test.go b/x/crypto/pbkdf2/pbkdf2_test.go index ec10daebb30..8f74063ff88 100644 --- a/x/crypto/pbkdf2/pbkdf2_test.go +++ b/x/crypto/pbkdf2/pbkdf2_test.go @@ -6,9 +6,10 @@ package pbkdf2 import ( "bytes" - "hash" "testing" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/crypto/sha256" ) diff --git a/x/crypto/pkcs12/pkcs12_test.go b/x/crypto/pkcs12/pkcs12_test.go index 7444e59960e..0daaebeb58b 100644 --- a/x/crypto/pkcs12/pkcs12_test.go +++ b/x/crypto/pkcs12/pkcs12_test.go @@ -5,11 +5,12 @@ package pkcs12 import ( - "crypto/tls" "encoding/base64" "encoding/pem" "testing" + "github.com/runZeroInc/excrypto/crypto/tls" + "github.com/runZeroInc/excrypto/crypto/rsa" ) diff --git a/x/crypto/ripemd160/ripemd160.go b/x/crypto/ripemd160/ripemd160.go index e7fd3144b17..fbcd18a8249 100644 --- a/x/crypto/ripemd160/ripemd160.go +++ b/x/crypto/ripemd160/ripemd160.go @@ -14,7 +14,7 @@ package ripemd160 // http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/salsa20/salsa/_asm/go.mod b/x/crypto/salsa20/salsa/_asm/go.mod index 9d1f856ef79..6243c0d2ff4 100644 --- a/x/crypto/salsa20/salsa/_asm/go.mod +++ b/x/crypto/salsa20/salsa/_asm/go.mod @@ -1,6 +1,6 @@ module salsa20/salsa/_asm -go 1.23 +go 1.24 require ( github.com/mmcloughlin/avo v0.6.0 diff --git a/x/crypto/sha3/hashes.go b/x/crypto/sha3/hashes.go index d6dfee3dc48..d09ba87f6a1 100644 --- a/x/crypto/sha3/hashes.go +++ b/x/crypto/sha3/hashes.go @@ -9,7 +9,7 @@ package sha3 // bytes. import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto" ) diff --git a/x/crypto/sha3/sha3.go b/x/crypto/sha3/sha3.go index 6658c44479b..2088809582f 100644 --- a/x/crypto/sha3/sha3.go +++ b/x/crypto/sha3/sha3.go @@ -5,11 +5,12 @@ package sha3 import ( - "crypto/subtle" "encoding/binary" "errors" "unsafe" + "github.com/runZeroInc/excrypto/crypto/subtle" + "golang.org/x/sys/cpu" ) diff --git a/x/crypto/sha3/sha3_s390x.go b/x/crypto/sha3/sha3_s390x.go index 00d8034ae62..c6fa9ec8ca1 100644 --- a/x/crypto/sha3/sha3_s390x.go +++ b/x/crypto/sha3/sha3_s390x.go @@ -11,7 +11,7 @@ package sha3 // instructions to compute SHA-3 and SHAKE hashes on IBM Z. import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "golang.org/x/sys/cpu" ) diff --git a/x/crypto/sha3/sha3_test.go b/x/crypto/sha3/sha3_test.go index d97a970b1a0..981614c56ab 100644 --- a/x/crypto/sha3/sha3_test.go +++ b/x/crypto/sha3/sha3_test.go @@ -17,12 +17,13 @@ import ( "encoding/hex" "encoding/json" "fmt" - "hash" "io" "math/rand" "os" "strings" "testing" + + "github.com/runZeroInc/excrypto/hash" ) const ( diff --git a/x/crypto/sha3/shake.go b/x/crypto/sha3/shake.go index a6b3a4281f5..cb1456d9b71 100644 --- a/x/crypto/sha3/shake.go +++ b/x/crypto/sha3/shake.go @@ -19,9 +19,10 @@ import ( "bytes" "encoding/binary" "errors" - "hash" "io" "math/bits" + + "github.com/runZeroInc/excrypto/hash" ) // ShakeHash defines the interface to hash functions that support diff --git a/x/crypto/ssh/agent/client_test.go b/x/crypto/ssh/agent/client_test.go index 42aec7782f7..d004eccd1d8 100644 --- a/x/crypto/ssh/agent/client_test.go +++ b/x/crypto/ssh/agent/client_test.go @@ -6,7 +6,6 @@ package agent import ( "bytes" - "crypto/rand" "errors" "io" "net" @@ -19,6 +18,8 @@ import ( "testing" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/ssh" ) diff --git a/x/crypto/ssh/agent/keyring.go b/x/crypto/ssh/agent/keyring.go index 411661f939c..db2c38add0b 100644 --- a/x/crypto/ssh/agent/keyring.go +++ b/x/crypto/ssh/agent/keyring.go @@ -6,12 +6,13 @@ package agent import ( "bytes" - "crypto/rand" "errors" "fmt" "sync" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/subtle" "github.com/runZeroInc/excrypto/x/crypto/ssh" ) diff --git a/x/crypto/ssh/agent/server_test.go b/x/crypto/ssh/agent/server_test.go index c5ae81cc6a4..0f3fa8933e4 100644 --- a/x/crypto/ssh/agent/server_test.go +++ b/x/crypto/ssh/agent/server_test.go @@ -5,13 +5,14 @@ package agent import ( - "crypto/rand" "fmt" pseudorand "math/rand" "reflect" "strings" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/x/crypto/ssh" ) diff --git a/x/crypto/ssh/agent/testdata_test.go b/x/crypto/ssh/agent/testdata_test.go index 57f7b304bb8..57f5d7c9457 100644 --- a/x/crypto/ssh/agent/testdata_test.go +++ b/x/crypto/ssh/agent/testdata_test.go @@ -9,9 +9,10 @@ package agent import ( - "crypto/rand" "fmt" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/ssh" "github.com/runZeroInc/excrypto/x/crypto/ssh/testdata" ) diff --git a/x/crypto/ssh/certs_test.go b/x/crypto/ssh/certs_test.go index ed8250beb6f..d91d5b907be 100644 --- a/x/crypto/ssh/certs_test.go +++ b/x/crypto/ssh/certs_test.go @@ -6,7 +6,6 @@ package ssh import ( "bytes" - "crypto/rand" "fmt" "io" "net" @@ -14,6 +13,8 @@ import ( "testing" "time" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" "github.com/runZeroInc/excrypto/x/crypto/ssh/testdata" diff --git a/x/crypto/ssh/cipher.go b/x/crypto/ssh/cipher.go index 53969d9d225..1d1b9430043 100644 --- a/x/crypto/ssh/cipher.go +++ b/x/crypto/ssh/cipher.go @@ -8,9 +8,10 @@ import ( "encoding/binary" "errors" "fmt" - "hash" "io" + "github.com/runZeroInc/excrypto/hash" + "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" "github.com/runZeroInc/excrypto/crypto/des" diff --git a/x/crypto/ssh/cipher_test.go b/x/crypto/ssh/cipher_test.go index 00ad6e8bfea..e33fef3da71 100644 --- a/x/crypto/ssh/cipher_test.go +++ b/x/crypto/ssh/cipher_test.go @@ -6,11 +6,12 @@ package ssh import ( "bytes" - "crypto/rand" "encoding/binary" "io" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/x/crypto/chacha20" "github.com/runZeroInc/excrypto/x/crypto/internal/poly1305" diff --git a/x/crypto/ssh/client_auth_test.go b/x/crypto/ssh/client_auth_test.go index ec27133a39b..997b3a4365a 100644 --- a/x/crypto/ssh/client_auth_test.go +++ b/x/crypto/ssh/client_auth_test.go @@ -6,7 +6,6 @@ package ssh import ( "bytes" - "crypto/rand" "errors" "fmt" "io" @@ -16,6 +15,8 @@ import ( "runtime" "strings" "testing" + + "crypto/rand" ) type keyboardInteractive map[string]string diff --git a/x/crypto/ssh/client_research.go b/x/crypto/ssh/client_research.go index b1691149583..e42683a72d2 100644 --- a/x/crypto/ssh/client_research.go +++ b/x/crypto/ssh/client_research.go @@ -181,9 +181,10 @@ func (uac *UnauthClientConn) Authenticate(authMethod AuthMethod, extensions map[ return ExpAuthResult(ares), methods, err } -func (uac *UnauthClientConn) Mux() (Conn, <-chan NewChannel, <-chan *Request) { +func (uac *UnauthClientConn) Mux(ignoreChannelOpenReply bool) (Conn, <-chan NewChannel, <-chan *Request) { uac.c.mux = newMux(uac.c.transport) uac.c.mux.timeout = uac.Config.Timeout + uac.c.mux.ignoreChannelOpenReply = ignoreChannelOpenReply return uac.c, uac.c.mux.incomingChannels, uac.c.mux.incomingRequests } @@ -213,6 +214,52 @@ func (uac *UnauthClientConn) WriteMsgUserAuthSuccess() error { return nil } +func (uac *UnauthClientConn) WriteRaw(raw []byte, readReply bool) (res []byte, err error) { + c := uac.c + if err = c.transport.writePacket(raw); err != nil { + return nil, err + } + if readReply { + res, err = c.transport.readPacket() + } + return +} + +func (uac *UnauthClientConn) ReadRaw() ([]byte, error) { + c := uac.c + return c.transport.readPacket() +} + +func (uac *UnauthClientConn) BuildChannelOpen(id uint32, name string, payload []byte) []byte { + msg := &channelOpenMsg{ + ChanType: name, + PeersWindow: 65536, + MaxPacketSize: 425984, + TypeSpecificData: payload, + PeersID: id, + } + return Marshal(msg) +} + +func (uac *UnauthClientConn) BuildChannelRequest(id uint32, name string, payload []byte, wantReply bool) []byte { + + msg := channelRequestMsg{ + PeersID: id, + Request: name, + WantReply: wantReply, + RequestSpecificData: payload, + } + return Marshal(msg) +} + +func (uac *UnauthClientConn) BuildChannelRequestString(id uint32, name string, payload string, wantReply bool) []byte { + req := execMsg{ // Struct with a single string field + Command: payload, + } + raw := Marshal(&req) + return uac.BuildChannelRequest(id, name, raw, wantReply) +} + // Setenv sets an environment variable that will be applied to any // command executed by Shell or Run. func (s *Session) SetenvNoReply(name, value string) error { diff --git a/x/crypto/ssh/client_test.go b/x/crypto/ssh/client_test.go index 2621f0ea527..472484727dc 100644 --- a/x/crypto/ssh/client_test.go +++ b/x/crypto/ssh/client_test.go @@ -6,12 +6,13 @@ package ssh import ( "bytes" - "crypto/rand" "errors" "fmt" "net" "strings" "testing" + + "crypto/rand" ) func TestClientVersion(t *testing.T) { diff --git a/x/crypto/ssh/common.go b/x/crypto/ssh/common.go index 538a4ba8d4f..4932b1ba23d 100644 --- a/x/crypto/ssh/common.go +++ b/x/crypto/ssh/common.go @@ -5,12 +5,13 @@ package ssh import ( - "crypto/rand" "fmt" "io" "math" "sync" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" _ "github.com/runZeroInc/excrypto/crypto/sha1" _ "github.com/runZeroInc/excrypto/crypto/sha256" diff --git a/x/crypto/ssh/example_test.go b/x/crypto/ssh/example_test.go index f0a38183b03..5846495948a 100644 --- a/x/crypto/ssh/example_test.go +++ b/x/crypto/ssh/example_test.go @@ -7,7 +7,6 @@ package ssh_test import ( "bufio" "bytes" - "crypto/rand" "fmt" "log" "net" @@ -17,6 +16,8 @@ import ( "strings" "sync" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/rsa" "github.com/runZeroInc/excrypto/x/crypto/ssh" "github.com/runZeroInc/excrypto/x/crypto/ssh/terminal" diff --git a/x/crypto/ssh/handshake.go b/x/crypto/ssh/handshake.go index d16107186d3..6bcf46e70a6 100644 --- a/x/crypto/ssh/handshake.go +++ b/x/crypto/ssh/handshake.go @@ -5,7 +5,6 @@ package ssh import ( - "crypto/rand" "errors" "fmt" "io" @@ -13,6 +12,8 @@ import ( "net" "strings" "sync" + + "crypto/rand" ) // debugHandshake, if set, prints messages sent and received. Key @@ -25,6 +26,11 @@ const debugHandshake = false // quickly. const chanSize = 16 +// maxPendingPackets sets the maximum number of packets to queue while waiting +// for KEX to complete. This limits the total pending data to maxPendingPackets +// * maxPacket bytes, which is ~16.8MB. +const maxPendingPackets = 64 + // keyingTransport is a packet based transport that supports key // changes. It need not be thread-safe. It should pass through // msgNewKeys in both directions. @@ -73,7 +79,11 @@ type handshakeTransport struct { incoming chan []byte readError error - mu sync.Mutex + mu sync.Mutex + // Condition for the above mutex. It is used to notify a completed key + // exchange or a write failure. Writes can wait for this condition while a + // key exchange is in progress. + writeCond *sync.Cond writeError error sentInitPacket []byte sentInitMsg *kexInitMsg @@ -82,7 +92,11 @@ type handshakeTransport struct { otherInitPacket []byte otherInitMsg *kexInitMsg - pendingPackets [][]byte // Used when a key exchange is in progress. + // Used to queue writes when a key exchange is in progress. The length is + // limited by pendingPacketsSize. Once full, writes will block until the key + // exchange is completed or an error occurs. If not empty, it is emptied + // all at once when the key exchange is completed in kexLoop. + pendingPackets [][]byte writePacketsLeft uint32 writeBytesLeft int64 userAuthComplete bool // whether the user authentication phase is complete @@ -139,6 +153,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, config: config, } + t.writeCond = sync.NewCond(&t.mu) t.resetReadThresholds() t.resetWriteThresholds() @@ -265,6 +280,7 @@ func (t *handshakeTransport) recordWriteError(err error) { defer t.mu.Unlock() if t.writeError == nil && err != nil { t.writeError = err + t.writeCond.Broadcast() } } @@ -367,6 +383,8 @@ write: } } t.pendingPackets = t.pendingPackets[:0] + // Unblock writePacket if waiting for KEX. + t.writeCond.Broadcast() t.mu.Unlock() } @@ -581,11 +599,20 @@ func (t *handshakeTransport) writePacket(p []byte) error { } if t.sentInitMsg != nil { - // Copy the packet so the writer can reuse the buffer. - cp := make([]byte, len(p)) - copy(cp, p) - t.pendingPackets = append(t.pendingPackets, cp) - return nil + if len(t.pendingPackets) < maxPendingPackets { + // Copy the packet so the writer can reuse the buffer. + cp := make([]byte, len(p)) + copy(cp, p) + t.pendingPackets = append(t.pendingPackets, cp) + return nil + } + for t.sentInitMsg != nil { + // Block and wait for KEX to complete or an error. + t.writeCond.Wait() + if t.writeError != nil { + return t.writeError + } + } } if t.writeBytesLeft > 0 { @@ -602,6 +629,7 @@ func (t *handshakeTransport) writePacket(p []byte) error { if err := t.pushPacket(p); err != nil { t.writeError = err + t.writeCond.Broadcast() } return nil diff --git a/x/crypto/ssh/handshake_test.go b/x/crypto/ssh/handshake_test.go index 2bc607b6493..2e9e892dd6d 100644 --- a/x/crypto/ssh/handshake_test.go +++ b/x/crypto/ssh/handshake_test.go @@ -6,7 +6,6 @@ package ssh import ( "bytes" - "crypto/rand" "errors" "fmt" "io" @@ -16,6 +15,8 @@ import ( "strings" "sync" "testing" + + "crypto/rand" ) type testChecker struct { @@ -539,6 +540,226 @@ func TestDisconnect(t *testing.T) { } } +type mockKeyingTransport struct { + packetConn + kexInitAllowed chan struct{} + kexInitSent chan struct{} +} + +func (n *mockKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { + return nil +} + +func (n *mockKeyingTransport) writePacket(packet []byte) error { + if packet[0] == msgKexInit { + <-n.kexInitAllowed + n.kexInitSent <- struct{}{} + } + return n.packetConn.writePacket(packet) +} + +func (n *mockKeyingTransport) readPacket() ([]byte, error) { + return n.packetConn.readPacket() +} + +func (n *mockKeyingTransport) setStrictMode() error { return nil } + +func (n *mockKeyingTransport) setInitialKEXDone() {} + +func TestHandshakePendingPacketsWait(t *testing.T) { + a, b := memPipe() + + trS := &mockKeyingTransport{ + packetConn: a, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trS.kexInitAllowed <- struct{}{} + + trC := &mockKeyingTransport{ + packetConn: b, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trC.kexInitAllowed <- struct{}{} + + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", nil) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server := newServerTransport(trS, v, v, serverConf) + + if err := server.waitSession(); err != nil { + t.Fatalf("server.waitSession: %v", err) + } + if err := client.waitSession(); err != nil { + t.Fatalf("client.waitSession: %v", err) + } + + <-trC.kexInitSent + <-trS.kexInitSent + + // Allow and request new KEX server side. + trS.kexInitAllowed <- struct{}{} + server.requestKeyExchange() + // Wait until the KEX init is sent. + <-trS.kexInitSent + // The client is not allowed to respond to the KEX, so writes will be + // blocked on the server side once the packets queue is full. + for i := 0; i < maxPendingPackets; i++ { + p := []byte{msgRequestSuccess, byte(i)} + if err := server.writePacket(p); err != nil { + t.Errorf("unexpected write error: %v", err) + } + } + // The packets queue is now full, the next write will block. + server.mu.Lock() + if len(server.pendingPackets) != maxPendingPackets { + t.Errorf("unexpected pending packets size; got: %d, want: %d", len(server.pendingPackets), maxPendingPackets) + } + server.mu.Unlock() + + writeDone := make(chan struct{}) + go func() { + defer close(writeDone) + + p := []byte{msgRequestSuccess, byte(65)} + // This write will block until KEX completes. + err := server.writePacket(p) + if err != nil { + t.Errorf("unexpected write error: %v", err) + } + }() + + // Consume packets on the client side + readDone := make(chan bool) + go func() { + defer close(readDone) + + for { + if _, err := client.readPacket(); err != nil { + if err != io.EOF { + t.Errorf("unexpected read error: %v", err) + } + break + } + } + }() + + // Allow the client to reply to the KEX and so unblock the write goroutine. + trC.kexInitAllowed <- struct{}{} + <-trC.kexInitSent + <-writeDone + // Close the client to unblock the read goroutine. + client.Close() + <-readDone + server.Close() +} + +func TestHandshakePendingPacketsError(t *testing.T) { + a, b := memPipe() + + trS := &mockKeyingTransport{ + packetConn: a, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trS.kexInitAllowed <- struct{}{} + + trC := &mockKeyingTransport{ + packetConn: b, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trC.kexInitAllowed <- struct{}{} + + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", nil) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server := newServerTransport(trS, v, v, serverConf) + + if err := server.waitSession(); err != nil { + t.Fatalf("server.waitSession: %v", err) + } + if err := client.waitSession(); err != nil { + t.Fatalf("client.waitSession: %v", err) + } + + <-trC.kexInitSent + <-trS.kexInitSent + + // Allow and request new KEX server side. + trS.kexInitAllowed <- struct{}{} + server.requestKeyExchange() + // Wait until the KEX init is sent. + <-trS.kexInitSent + // The client is not allowed to respond to the KEX, so writes will be + // blocked on the server side once the packets queue is full. + for i := 0; i < maxPendingPackets; i++ { + p := []byte{msgRequestSuccess, byte(i)} + if err := server.writePacket(p); err != nil { + t.Errorf("unexpected write error: %v", err) + } + } + // The packets queue is now full, the next write will block. + writeDone := make(chan struct{}) + go func() { + defer close(writeDone) + + p := []byte{msgRequestSuccess, byte(65)} + // This write will block until KEX completes. + err := server.writePacket(p) + if err != io.EOF { + t.Errorf("unexpected write error: %v", err) + } + }() + + // Consume packets on the client side + readDone := make(chan bool) + go func() { + defer close(readDone) + + for { + if _, err := client.readPacket(); err != nil { + if err != io.EOF { + t.Errorf("unexpected read error: %v", err) + } + break + } + } + }() + + // Close the server to unblock the write after an error + server.Close() + <-writeDone + // Unblock the pending write and close the client to unblock the read + // goroutine. + trC.kexInitAllowed <- struct{}{} + client.Close() + <-readDone +} + func TestHandshakeRekeyDefault(t *testing.T) { clientConf := &ClientConfig{ Config: Config{ diff --git a/x/crypto/ssh/kex.go b/x/crypto/ssh/kex.go index bd3f630fa51..4a40e3129d2 100644 --- a/x/crypto/ssh/kex.go +++ b/x/crypto/ssh/kex.go @@ -5,13 +5,14 @@ package ssh import ( - "crypto/rand" "encoding/binary" "errors" "fmt" "io" "math/big" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/elliptic" diff --git a/x/crypto/ssh/kex_test.go b/x/crypto/ssh/kex_test.go index cb7f66a5092..aee4a998f68 100644 --- a/x/crypto/ssh/kex_test.go +++ b/x/crypto/ssh/kex_test.go @@ -7,11 +7,12 @@ package ssh // Key exchange tests. import ( - "crypto/rand" "fmt" "reflect" "sync" "testing" + + "crypto/rand" ) // Runs multiple key exchanges concurrent to detect potential data races with diff --git a/x/crypto/ssh/keys.go b/x/crypto/ssh/keys.go index f6d777e009a..986c76ebba4 100644 --- a/x/crypto/ssh/keys.go +++ b/x/crypto/ssh/keys.go @@ -6,7 +6,6 @@ package ssh import ( "bytes" - "crypto/rand" "encoding/base64" "encoding/binary" "encoding/hex" @@ -17,6 +16,8 @@ import ( "math/big" "strings" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto" "github.com/runZeroInc/excrypto/crypto/aes" "github.com/runZeroInc/excrypto/crypto/cipher" diff --git a/x/crypto/ssh/keys_test.go b/x/crypto/ssh/keys_test.go index e514f77db3d..69e59025598 100644 --- a/x/crypto/ssh/keys_test.go +++ b/x/crypto/ssh/keys_test.go @@ -6,7 +6,6 @@ package ssh import ( "bytes" - "crypto/rand" "encoding/base64" "encoding/hex" "encoding/pem" @@ -17,6 +16,8 @@ import ( "strings" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/dsa" "github.com/runZeroInc/excrypto/crypto/ecdsa" "github.com/runZeroInc/excrypto/crypto/ed25519" diff --git a/x/crypto/ssh/knownhosts/knownhosts.go b/x/crypto/ssh/knownhosts/knownhosts.go index e9dc06cfb52..8de4e7196c9 100644 --- a/x/crypto/ssh/knownhosts/knownhosts.go +++ b/x/crypto/ssh/knownhosts/knownhosts.go @@ -10,7 +10,6 @@ package knownhosts import ( "bufio" "bytes" - "crypto/rand" "encoding/base64" "errors" "fmt" @@ -19,6 +18,8 @@ import ( "os" "strings" + "crypto/rand" + "github.com/runZeroInc/excrypto/crypto/hmac" "github.com/runZeroInc/excrypto/crypto/sha1" "github.com/runZeroInc/excrypto/x/crypto/ssh" @@ -302,8 +303,8 @@ func (k *KnownKey) String() string { // applications can offer an interactive prompt to the user. type KeyError struct { // Want holds the accepted host keys. For each key algorithm, - // there can be one hostkey. If Want is empty, the host is - // unknown. If Want is non-empty, there was a mismatch, which + // there can be multiple hostkeys. If Want is empty, the host + // is unknown. If Want is non-empty, there was a mismatch, which // can signify a MITM attack. Want []KnownKey } @@ -358,34 +359,20 @@ func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { // is just a key for the IP address, but not for the // hostname? - // Algorithm => key. - knownKeys := map[string]KnownKey{} - for _, l := range db.lines { - if l.match(a) { - typ := l.knownKey.Key.Type() - if _, ok := knownKeys[typ]; !ok { - knownKeys[typ] = l.knownKey - } - } - } - keyErr := &KeyError{} - for _, v := range knownKeys { - keyErr.Want = append(keyErr.Want, v) - } - // Unknown remote host. - if len(knownKeys) == 0 { - return keyErr - } + for _, l := range db.lines { + if !l.match(a) { + continue + } - // If the remote host starts using a different, unknown key type, we - // also interpret that as a mismatch. - if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { - return keyErr + keyErr.Want = append(keyErr.Want, l.knownKey) + if keyEq(l.knownKey.Key, remoteKey) { + return nil + } } - return nil + return keyErr } // The Read function parses file contents. diff --git a/x/crypto/ssh/knownhosts/knownhosts_test.go b/x/crypto/ssh/knownhosts/knownhosts_test.go index a59ab057bfd..f2907428aee 100644 --- a/x/crypto/ssh/knownhosts/knownhosts_test.go +++ b/x/crypto/ssh/knownhosts/knownhosts_test.go @@ -201,17 +201,6 @@ func TestHostNamePrecedence(t *testing.T) { } } -func TestDBOrderingPrecedenceKeyType(t *testing.T) { - str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) - db := testDB(t, str) - - if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { - t.Errorf("check succeeded") - } else if _, ok := err.(*KeyError); !ok { - t.Errorf("got %T, want *KeyError", err) - } -} - func TestNegate(t *testing.T) { str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) db := testDB(t, str) @@ -354,3 +343,16 @@ func TestHashedHostkeyCheck(t *testing.T) { t.Errorf("got error %v, want %v", got, want) } } + +func TestIssue36126(t *testing.T) { + str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) + db := testDB(t, str) + + if err := db.check("server.org:22", testAddr, edKey); err != nil { + t.Errorf("should have passed the check, got %v", err) + } + + if err := db.check("server.org:22", testAddr, alternateEdKey); err != nil { + t.Errorf("should have passed the check, got %v", err) + } +} diff --git a/x/crypto/ssh/mac.go b/x/crypto/ssh/mac.go index 5984b9c9c5a..083f7655a77 100644 --- a/x/crypto/ssh/mac.go +++ b/x/crypto/ssh/mac.go @@ -7,7 +7,7 @@ package ssh // Message authentication support import ( - "hash" + "github.com/runZeroInc/excrypto/hash" "github.com/runZeroInc/excrypto/crypto/hmac" "github.com/runZeroInc/excrypto/crypto/sha1" diff --git a/x/crypto/ssh/messages.go b/x/crypto/ssh/messages.go index b55f860564f..118427bc059 100644 --- a/x/crypto/ssh/messages.go +++ b/x/crypto/ssh/messages.go @@ -818,6 +818,8 @@ func decode(packet []byte) (interface{}, error) { return new(userAuthSuccessMsg), nil case msgUserAuthFailure: msg = new(userAuthFailureMsg) + case msgUserAuthBanner: + msg = new(userAuthBannerMsg) case msgUserAuthPubKeyOk: msg = new(userAuthPubKeyOkMsg) case msgGlobalRequest: diff --git a/x/crypto/ssh/messages_test.go b/x/crypto/ssh/messages_test.go index e79076412ab..d8691bd0ba9 100644 --- a/x/crypto/ssh/messages_test.go +++ b/x/crypto/ssh/messages_test.go @@ -206,6 +206,62 @@ func TestMarshalMultiTag(t *testing.T) { } } +func TestDecode(t *testing.T) { + rnd := rand.New(rand.NewSource(0)) + kexInit := new(kexInitMsg).Generate(rnd, 10).Interface() + kexDHInit := new(kexDHInitMsg).Generate(rnd, 10).Interface() + kexDHReply := new(kexDHReplyMsg) + kexDHReply.Y = randomInt(rnd) + // Note: userAuthSuccessMsg can't be tested directly since it + // doesn't have a field for sshtype. So it's tested separately + // at the end. + decodeMessageTypes := []interface{}{ + new(disconnectMsg), + new(serviceRequestMsg), + new(serviceAcceptMsg), + new(extInfoMsg), + kexInit, + kexDHInit, + kexDHReply, + new(userAuthRequestMsg), + new(userAuthFailureMsg), + new(userAuthBannerMsg), + new(userAuthPubKeyOkMsg), + new(globalRequestMsg), + new(globalRequestSuccessMsg), + new(globalRequestFailureMsg), + new(channelOpenMsg), + new(channelDataMsg), + new(channelOpenConfirmMsg), + new(channelOpenFailureMsg), + new(windowAdjustMsg), + new(channelEOFMsg), + new(channelCloseMsg), + new(channelRequestMsg), + new(channelRequestSuccessMsg), + new(channelRequestFailureMsg), + new(userAuthGSSAPIToken), + new(userAuthGSSAPIMIC), + new(userAuthGSSAPIErrTok), + new(userAuthGSSAPIError), + } + for _, msg := range decodeMessageTypes { + decoded, err := decode(Marshal(msg)) + if err != nil { + t.Errorf("error decoding %T", msg) + } else if reflect.TypeOf(msg) != reflect.TypeOf(decoded) { + t.Errorf("error decoding %T, unexpected %T", msg, decoded) + } + } + + userAuthSuccess, err := decode([]byte{msgUserAuthSuccess}) + if err != nil { + t.Errorf("error decoding userAuthSuccessMsg") + } else if reflect.TypeOf(userAuthSuccess) != reflect.TypeOf((*userAuthSuccessMsg)(nil)) { + t.Errorf("error decoding userAuthSuccessMsg, unexpected %T", userAuthSuccess) + } +} + func randomBytes(out []byte, rand *rand.Rand) { for i := 0; i < len(out); i++ { out[i] = byte(rand.Int31()) diff --git a/x/crypto/ssh/mux.go b/x/crypto/ssh/mux.go index 5f2af636504..22b1f43459c 100644 --- a/x/crypto/ssh/mux.go +++ b/x/crypto/ssh/mux.go @@ -99,6 +99,9 @@ type mux struct { errCond *sync.Cond err error timeout time.Duration + + // Research + ignoreChannelOpenReply bool } // When debugging, each new chanList instantiation has a different @@ -233,6 +236,9 @@ func (m *mux) onePacket() error { return m.handleChannelOpen(packet) case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: return m.handleGlobalPacket(packet) + case msgExtInfo: + // Research: drop these for now + return nil case msgPing: var msg pingMsg if err := Unmarshal(packet, &msg); err != nil { @@ -330,6 +336,12 @@ func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { m.timeout = time.Hour * 4 } + // Research: enable skipping of the channel open reply + if m.ignoreChannelOpenReply { + ch.decided = true + return ch, nil + } + t := time.NewTimer(m.timeout) defer t.Stop() diff --git a/x/crypto/ssh/tcpip.go b/x/crypto/ssh/tcpip.go index ef5059a11d7..93d844f0351 100644 --- a/x/crypto/ssh/tcpip.go +++ b/x/crypto/ssh/tcpip.go @@ -459,7 +459,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel return nil, err } go DiscardRequests(in) - return ch, err + return ch, nil } type tcpChan struct { diff --git a/x/crypto/ssh/test/cert_test.go b/x/crypto/ssh/test/cert_test.go index a6c1f778b41..90fa509cbdc 100644 --- a/x/crypto/ssh/test/cert_test.go +++ b/x/crypto/ssh/test/cert_test.go @@ -8,9 +8,10 @@ package test import ( "bytes" - "crypto/rand" "testing" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/ssh" ) diff --git a/x/crypto/ssh/test/test_unix_test.go b/x/crypto/ssh/test/test_unix_test.go index 03afdc2865b..889b78e9a23 100644 --- a/x/crypto/ssh/test/test_unix_test.go +++ b/x/crypto/ssh/test/test_unix_test.go @@ -10,7 +10,6 @@ package test import ( "bytes" - "crypto/rand" "encoding/base64" "fmt" "log" @@ -22,6 +21,8 @@ import ( "testing" "text/template" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/internal/testenv" "github.com/runZeroInc/excrypto/x/crypto/ssh" "github.com/runZeroInc/excrypto/x/crypto/ssh/testdata" diff --git a/x/crypto/ssh/test/testdata_test.go b/x/crypto/ssh/test/testdata_test.go index ecd1d7b33e0..061f83b574a 100644 --- a/x/crypto/ssh/test/testdata_test.go +++ b/x/crypto/ssh/test/testdata_test.go @@ -9,9 +9,10 @@ package test import ( - "crypto/rand" "fmt" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/ssh" "github.com/runZeroInc/excrypto/x/crypto/ssh/testdata" ) diff --git a/x/crypto/ssh/testdata_test.go b/x/crypto/ssh/testdata_test.go index 89c9770a255..0ca721c7634 100644 --- a/x/crypto/ssh/testdata_test.go +++ b/x/crypto/ssh/testdata_test.go @@ -9,9 +9,10 @@ package ssh import ( - "crypto/rand" "fmt" + "crypto/rand" + "github.com/runZeroInc/excrypto/x/crypto/ssh/testdata" ) diff --git a/x/crypto/ssh/transport_test.go b/x/crypto/ssh/transport_test.go index e029419e393..35002ae7013 100644 --- a/x/crypto/ssh/transport_test.go +++ b/x/crypto/ssh/transport_test.go @@ -6,10 +6,11 @@ package ssh import ( "bytes" - "crypto/rand" "encoding/binary" "strings" "testing" + + "crypto/rand" ) func TestReadVersion(t *testing.T) { diff --git a/x/crypto/x509roots/fallback/bundle.go b/x/crypto/x509roots/fallback/bundle.go index 36ffa969d69..49d9024f9c9 100644 --- a/x/crypto/x509roots/fallback/bundle.go +++ b/x/crypto/x509roots/fallback/bundle.go @@ -1,43 +1,74 @@ // Code generated by gen_fallback_bundle.go; DO NOT EDIT. -//go:build go1.20 - package fallback -import "github.com/runZeroInc/excrypto/crypto/x509" -import "encoding/pem" +import ( + "fmt" + "time" + + "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/encoding/pem" +) + +type unparsedCertificate struct { + cn string + sha256Hash string + pem string -func mustParse(b []byte) []*x509.Certificate { - var roots []*x509.Certificate - for len(b) > 0 { - var block *pem.Block - block, b = pem.Decode(b) + // possible constraints + distrustAfter string +} + +type parsedCertificate struct { + cert *x509.Certificate + constraints []func([]*x509.Certificate) error +} + +func mustParse(unparsedCerts []unparsedCertificate) []parsedCertificate { + var b []parsedCertificate + for _, unparsed := range unparsedCerts { + block, rest := pem.Decode([]byte(unparsed.pem)) if block == nil { - break + panic(fmt.Sprintf("unexpected nil PEM block for %q", unparsed.cn)) + } + if len(rest) != 0 { + panic(fmt.Sprintf("unexpected trailing data in PEM for %q", unparsed.cn)) } if block.Type != "CERTIFICATE" { - panic("unexpected PEM block type: " + block.Type) + panic(fmt.Sprintf("unexpected PEM block type for %q: %s", unparsed.cn, block.Type)) } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { panic(err) } - roots = append(roots, cert) + parsed := parsedCertificate{cert: cert} + // parse possible constraints, this should check all fields of unparsedCertificate. + if unparsed.distrustAfter != "" { + distrustAfter, err := time.Parse(time.RFC3339, unparsed.distrustAfter) + if err != nil { + panic(fmt.Sprintf("failed to parse distrustAfter %q: %s", unparsed.distrustAfter, err)) + } + parsed.constraints = append(parsed.constraints, func(chain []*x509.Certificate) error { + for _, c := range chain { + if c.NotBefore.After(distrustAfter) { + return fmt.Errorf("certificate issued after distrust-after date %q", distrustAfter) + } + } + return nil + }) + } + b = append(b, parsed) } - return roots + return b } -var bundle = mustParse([]byte(pemRoots)) +var parsedCertificates = mustParse(unparsedCertificates) -// Format of the PEM list is: -// * Subject common name -// * SHA256 hash -// * PEM block - -const pemRoots = ` -# CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -# d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4 ------BEGIN CERTIFICATE----- +var unparsedCertificates = []unparsedCertificate{ + { + cn: "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4", + pem: `-----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj @@ -62,9 +93,12 @@ G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- -# CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a -# 554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a", + sha256Hash: "554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb", + pem: `-----BEGIN CERTIFICATE----- MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S @@ -80,9 +114,12 @@ SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy v+c= -----END CERTIFICATE----- -# CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES -# 9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES", + sha256Hash: "9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113", + pem: `-----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ @@ -126,9 +163,12 @@ h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- -# CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT -# 55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT", + sha256Hash: "55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066", + pem: `-----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 @@ -161,9 +201,120 @@ ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- -# CN=Amazon Root CA 1,O=Amazon,C=US -# 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=AffirmTrust Commercial,O=AffirmTrust,C=US", + sha256Hash: "0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7", + pem: `-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Networking,O=AffirmTrust,C=US", + sha256Hash: "0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b", + pem: `-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US", + sha256Hash: "bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423", + pem: `-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Premium,O=AffirmTrust,C=US", + sha256Hash: "70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a", + pem: `-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Amazon Root CA 1,O=Amazon,C=US", + sha256Hash: "8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e", + pem: `-----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL @@ -183,9 +334,12 @@ o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy rqXRfboQnoZsG4q5WTP468SQvvG5 -----END CERTIFICATE----- -# CN=Amazon Root CA 2,O=Amazon,C=US -# 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Amazon Root CA 2,O=Amazon,C=US", + sha256Hash: "1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4", + pem: `-----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL @@ -216,9 +370,12 @@ n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE 9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT 4PsJYGw= -----END CERTIFICATE----- -# CN=Amazon Root CA 3,O=Amazon,C=US -# 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Amazon Root CA 3,O=Amazon,C=US", + sha256Hash: "18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4", + pem: `-----BEGIN CERTIFICATE----- MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG @@ -230,9 +387,12 @@ ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM YyRIHN8wfdVoOw== -----END CERTIFICATE----- -# CN=Amazon Root CA 4,O=Amazon,C=US -# e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Amazon Root CA 4,O=Amazon,C=US", + sha256Hash: "e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092", + pem: `-----BEGIN CERTIFICATE----- MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG @@ -245,9 +405,12 @@ MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW 1KyLa2tJElMzrdfkviT8tQp21KW8EA== -----END CERTIFICATE----- -# CN=Atos TrustedRoot 2011,O=Atos,C=DE -# f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Atos TrustedRoot 2011,O=Atos,C=DE", + sha256Hash: "f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474", + pem: `-----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM @@ -268,9 +431,12 @@ maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- -# CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE -# b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE", + sha256Hash: "b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8", + pem: `-----BEGIN CERTIFICATE----- MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 @@ -284,9 +450,12 @@ aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo 9H1/IISpQuQo -----END CERTIFICATE----- -# CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE -# 81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE", + sha256Hash: "81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f", + pem: `-----BEGIN CERTIFICATE----- MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 @@ -317,9 +486,12 @@ o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== -----END CERTIFICATE----- -# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES -# 57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES", + sha256Hash: "57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a", + pem: `-----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 @@ -354,9 +526,12 @@ f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV -----END CERTIFICATE----- -# CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN -# f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN", + sha256Hash: "f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae", + pem: `-----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz @@ -388,9 +563,12 @@ eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy r/6zcCwupvI= -----END CERTIFICATE----- -# CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN -# 574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN", + sha256Hash: "574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882", + pem: `-----BEGIN CERTIFICATE----- MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy @@ -404,9 +582,12 @@ AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA 94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B 43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== -----END CERTIFICATE----- -# CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -# 16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE", + sha256Hash: "16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb", + pem: `-----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX @@ -427,9 +608,12 @@ Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- -# CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO -# 9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO", + sha256Hash: "9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48", + pem: `-----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow @@ -460,9 +644,12 @@ I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= -----END CERTIFICATE----- -# CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO -# edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO", + sha256Hash: "edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d", + pem: `-----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow @@ -493,9 +680,12 @@ kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq 4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= -----END CERTIFICATE----- -# CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK -# e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK", + sha256Hash: "e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703", + pem: `-----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy @@ -526,9 +716,12 @@ G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- -# CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN -# 5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN", + sha256Hash: "5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd", + pem: `-----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx @@ -560,9 +753,12 @@ Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ 5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- -# CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -# 0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66", + pem: `-----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV @@ -587,9 +783,12 @@ zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB ZQ== -----END CERTIFICATE----- -# CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -# 1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7", + pem: `-----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT @@ -605,9 +804,12 @@ BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- -# CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -# 52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234", + pem: `-----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV @@ -641,9 +843,12 @@ QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl 0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB NVOFBkpdn627G190 -----END CERTIFICATE----- -# CN=Certainly Root E1,O=Certainly,C=US -# b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certainly Root E1,O=Certainly,C=US", + sha256Hash: "b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2", + pem: `-----BEGIN CERTIFICATE----- MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ @@ -656,9 +861,12 @@ hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- -# CN=Certainly Root R1,O=Certainly,C=US -# 77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certainly Root R1,O=Certainly,C=US", + sha256Hash: "77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0", + pem: `-----BEGIN CERTIFICATE----- MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 @@ -689,9 +897,12 @@ yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 OV+KmalBWQewLK8= -----END CERTIFICATE----- -# CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR -# d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR", + sha256Hash: "d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168", + pem: `-----BEGIN CERTIFICATE----- MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x @@ -727,9 +938,12 @@ Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw 3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= -----END CERTIFICATE----- -# CN=Certigna,O=Dhimyotis,C=FR -# e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certigna,O=Dhimyotis,C=FR", + sha256Hash: "e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d", + pem: `-----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ @@ -751,9 +965,12 @@ HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- -# CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL -# 6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL", + sha256Hash: "6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6", + pem: `-----BEGIN CERTIFICATE----- MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT @@ -768,9 +985,12 @@ EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= -----END CERTIFICATE----- -# CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL -# b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL", + sha256Hash: "b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804", + pem: `-----BEGIN CERTIFICATE----- MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG @@ -804,9 +1024,12 @@ XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P 5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi DrW5viSP -----END CERTIFICATE----- -# CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL -# 5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL", + sha256Hash: "5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e", + pem: `-----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU @@ -828,9 +1051,12 @@ J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- -# CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL -# fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL", + sha256Hash: "fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd", + pem: `-----BEGIN CERTIFICATE----- MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV @@ -863,9 +1089,12 @@ qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP 0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb -----END CERTIFICATE----- -# CN=CommScope Public Trust ECC Root-01,O=CommScope,C=US -# 11437cda7bb45e41365f45b39a38986b0de00def348e0c7bb0873633800bc38b ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CommScope Public Trust ECC Root-01,O=CommScope,C=US", + sha256Hash: "11437cda7bb45e41365f45b39a38986b0de00def348e0c7bb0873633800bc38b", + pem: `-----BEGIN CERTIFICATE----- MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa @@ -879,9 +1108,12 @@ hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg 2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS Um9poIyNStDuiw7LR47QjRE= -----END CERTIFICATE----- -# CN=CommScope Public Trust ECC Root-02,O=CommScope,C=US -# 2ffb7f813bbbb3c89ab4e8162d0f16d71509a830cc9d73c262e5140875d1ad4a ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CommScope Public Trust ECC Root-02,O=CommScope,C=US", + sha256Hash: "2ffb7f813bbbb3c89ab4e8162d0f16d71509a830cc9d73c262e5140875d1ad4a", + pem: `-----BEGIN CERTIFICATE----- MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa @@ -895,9 +1127,12 @@ hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV mkzw5l4lIhVtwodZ0LKOag== -----END CERTIFICATE----- -# CN=CommScope Public Trust RSA Root-01,O=CommScope,C=US -# 02bdf96e2a45dd9bf18fc7e1dbdf21a0379ba3c9c2610344cfd8d606fec1ed81 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CommScope Public Trust RSA Root-01,O=CommScope,C=US", + sha256Hash: "02bdf96e2a45dd9bf18fc7e1dbdf21a0379ba3c9c2610344cfd8d606fec1ed81", + pem: `-----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1 @@ -928,9 +1163,12 @@ lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw -----END CERTIFICATE----- -# CN=CommScope Public Trust RSA Root-02,O=CommScope,C=US -# ffe943d793424b4f7c440c1c3d648d5363f34b82dc87aa7a9f118fc5dee101f1 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=CommScope Public Trust RSA Root-02,O=CommScope,C=US", + sha256Hash: "ffe943d793424b4f7c440c1c3d648d5363f34b82dc87aa7a9f118fc5dee101f1", + pem: `-----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2 @@ -961,9 +1199,12 @@ lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670 v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 -----END CERTIFICATE----- -# CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE -# e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE", + sha256Hash: "e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044", + pem: `-----BEGIN CERTIFICATE----- MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 @@ -981,9 +1222,12 @@ PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV dWNbFJWcHwHP2NVypw87 -----END CERTIFICATE----- -# CN=D-TRUST BR Root CA 2 2023,O=D-Trust GmbH,C=DE -# 0552e6f83fdf65e8fa9670e666df28a4e21340b510cbe52566f97c4fb94b2bd1 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST BR Root CA 2 2023,O=D-Trust GmbH,C=DE", + sha256Hash: "0552e6f83fdf65e8fa9670e666df28a4e21340b510cbe52566f97c4fb94b2bd1", + pem: `-----BEGIN CERTIFICATE----- MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw @@ -1016,9 +1260,12 @@ Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ hJ65bvspmZDogNOfJA== -----END CERTIFICATE----- -# CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE -# 08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE", + sha256Hash: "08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db", + pem: `-----BEGIN CERTIFICATE----- MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 @@ -1036,9 +1283,12 @@ PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb gfM0agPnIjhQW+0ZT0MW -----END CERTIFICATE----- -# CN=D-TRUST EV Root CA 2 2023,O=D-Trust GmbH,C=DE -# 8e8221b2e7d4007836a1672f0dcc299c33bc07d316f132fa1a206d587150f1ce ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST EV Root CA 2 2023,O=D-Trust GmbH,C=DE", + sha256Hash: "8e8221b2e7d4007836a1672f0dcc299c33bc07d316f132fa1a206d587150f1ce", + pem: `-----BEGIN CERTIFICATE----- MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw @@ -1071,9 +1321,12 @@ gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh XBxvWHZks/wCuPWdCg== -----END CERTIFICATE----- -# CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE -# 49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE", + sha256Hash: "49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1", + pem: `-----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha @@ -1098,9 +1351,12 @@ zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y Johw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- -# CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE -# eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE", + sha256Hash: "eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881", + pem: `-----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw @@ -1125,9 +1381,12 @@ CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 -----END CERTIFICATE----- -# CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -# 3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c", + pem: `-----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv @@ -1149,9 +1408,12 @@ NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- -# CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US -# 7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185", + pem: `-----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv @@ -1173,9 +1435,12 @@ B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- -# CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US -# 7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2", + pem: `-----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg @@ -1190,9 +1455,12 @@ AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv 6pZjamVFkpUBtA== -----END CERTIFICATE----- -# CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -# 4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161", + pem: `-----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD @@ -1214,9 +1482,12 @@ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- -# CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US -# cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f", + pem: `-----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH @@ -1238,9 +1509,12 @@ Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- -# CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US -# 31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0", + pem: `-----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe @@ -1255,9 +1529,12 @@ AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 sycX -----END CERTIFICATE----- -# CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -# 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf", + pem: `-----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j @@ -1280,9 +1557,12 @@ Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +OkuE6N36B9K -----END CERTIFICATE----- -# CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US -# 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\\, Inc.,C=US", + sha256Hash: "018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05", + pem: `-----BEGIN CERTIFICATE----- MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 @@ -1296,9 +1576,12 @@ BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 DXZDjC5Ty3zfDBeWUA== -----END CERTIFICATE----- -# CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US -# 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\\, Inc.,C=US", + sha256Hash: "371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75", + pem: `-----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN @@ -1329,9 +1612,12 @@ MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ -----END CERTIFICATE----- -# CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US -# 552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988", + pem: `-----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg @@ -1363,9 +1649,131 @@ r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 /YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -----END CERTIFICATE----- -# CN=FIRMAPROFESIONAL CA ROOT-A WEB,O=Firmaprofesional SA,C=ES,2.5.4.97=#130f56415445532d413632363334303638 -# bef256daf26e9c69bdec1602359798f3caf71821a03e018257c53c65617f3d4a ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Entrust Root Certification Authority - EC1,OU=See www.entrust.net/legal-terms+OU=(c) 2012 Entrust\\, Inc. - for authorized use only,O=Entrust\\, Inc.,C=US", + sha256Hash: "02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5", + pem: `-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Entrust Root Certification Authority - G2,OU=See www.entrust.net/legal-terms+OU=(c) 2009 Entrust\\, Inc. - for authorized use only,O=Entrust\\, Inc.,C=US", + sha256Hash: "43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339", + pem: `-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Entrust Root Certification Authority,OU=www.entrust.net/CPS is incorporated by reference+OU=(c) 2006 Entrust\\, Inc.,O=Entrust\\, Inc.,C=US", + sha256Hash: "73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c", + pem: `-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Entrust.net Certification Authority (2048),OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)+OU=(c) 1999 Entrust.net Limited,O=Entrust.net", + sha256Hash: "6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177", + pem: `-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- +`, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=FIRMAPROFESIONAL CA ROOT-A WEB,O=Firmaprofesional SA,C=ES,2.5.4.97=#130f56415445532d413632363334303638", + sha256Hash: "bef256daf26e9c69bdec1602359798f3caf71821a03e018257c53c65617f3d4a", + pem: `-----BEGIN CERTIFICATE----- MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB @@ -1381,9 +1789,12 @@ PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG XSaQpYXFuXqUPoeovQA= -----END CERTIFICATE----- -# CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\,LTD.,C=CN -# bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\\,LTD.,C=CN", + sha256Hash: "bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893", + pem: `-----BEGIN CERTIFICATE----- MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 @@ -1415,9 +1826,50 @@ XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -----END CERTIFICATE----- -# CN=GTS Root R1,O=Google Trust Services LLC,C=US -# d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GLOBALTRUST 2020,O=e-commerce monitoring GmbH,C=AT", + sha256Hash: "9a296a5182d1d451a2e37f439b74daafa267523329f90f9a0d2007c334e23c9a", + pem: `-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- +`, + distrustAfter: "2024-06-30T00:00:00Z", + }, + { + cn: "CN=GTS Root R1,O=Google Trust Services LLC,C=US", + sha256Hash: "d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf", + pem: `-----BEGIN CERTIFICATE----- MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw @@ -1448,9 +1900,12 @@ Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT 2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c -----END CERTIFICATE----- -# CN=GTS Root R2,O=Google Trust Services LLC,C=US -# 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GTS Root R2,O=Google Trust Services LLC,C=US", + sha256Hash: "8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8", + pem: `-----BEGIN CERTIFICATE----- MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw @@ -1481,9 +1936,12 @@ JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV 7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl 6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL -----END CERTIFICATE----- -# CN=GTS Root R3,O=Google Trust Services LLC,C=US -# 34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GTS Root R3,O=Google Trust Services LLC,C=US", + sha256Hash: "34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48", + pem: `-----BEGIN CERTIFICATE----- MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw @@ -1496,9 +1954,12 @@ BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X -----END CERTIFICATE----- -# CN=GTS Root R4,O=Google Trust Services LLC,C=US -# 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GTS Root R4,O=Google Trust Services LLC,C=US", + sha256Hash: "349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d", + pem: `-----BEGIN CERTIFICATE----- MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw @@ -1511,9 +1972,12 @@ BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D 9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD -----END CERTIFICATE----- -# CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE -# ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE", + sha256Hash: "ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99", + pem: `-----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw @@ -1534,9 +1998,12 @@ AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- -# CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE -# cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE", + sha256Hash: "cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058", + pem: `-----BEGIN CERTIFICATE----- MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw @@ -1549,9 +2016,12 @@ DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ 7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 +RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= -----END CERTIFICATE----- -# CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE -# 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE", + sha256Hash: "4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9", + pem: `-----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy @@ -1582,9 +2052,12 @@ u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 -----END CERTIFICATE----- -# CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign -# b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign", + sha256Hash: "b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2", + pem: `-----BEGIN CERTIFICATE----- MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw @@ -1596,9 +2069,12 @@ HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ +wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -----END CERTIFICATE----- -# CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign -# 179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign", + sha256Hash: "179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924", + pem: `-----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX @@ -1612,9 +2088,12 @@ KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg 515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO xwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- -# CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign -# cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign", + sha256Hash: "cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b", + pem: `-----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 @@ -1635,9 +2114,12 @@ mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- -# CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign -# 2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign", + sha256Hash: "2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69", + pem: `-----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx @@ -1669,9 +2151,12 @@ JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R 8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= -----END CERTIFICATE----- -# CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\, Inc.,L=Scottsdale,ST=Arizona,C=US -# 45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda", + pem: `-----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp @@ -1694,9 +2179,12 @@ gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI 4uJEvlz36hz1 -----END CERTIFICATE----- -# CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR -# 3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR", + sha256Hash: "3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401", + pem: `-----BEGIN CERTIFICATE----- MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v @@ -1711,9 +2199,12 @@ AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps -----END CERTIFICATE----- -# CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR -# d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR", + sha256Hash: "d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d", + pem: `-----BEGIN CERTIFICATE----- MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg @@ -1746,9 +2237,12 @@ aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU 63ZTGI0RmLo= -----END CERTIFICATE----- -# CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR -# 44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR", + sha256Hash: "44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833", + pem: `-----BEGIN CERTIFICATE----- MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl @@ -1765,9 +2259,12 @@ C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- -# CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR -# a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR", + sha256Hash: "a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36", + pem: `-----BEGIN CERTIFICATE----- MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT @@ -1802,9 +2299,12 @@ pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 vm9qp/UsQu0yrbYhnr68 -----END CERTIFICATE----- -# CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\, Ltd.,C=TW -# f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\\, Ltd.,C=TW", + sha256Hash: "f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc", + pem: `-----BEGIN CERTIFICATE----- MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa @@ -1835,9 +2335,12 @@ kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== -----END CERTIFICATE----- -# CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK -# 5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK", + sha256Hash: "5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6", + pem: `-----BEGIN CERTIFICATE----- MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n @@ -1871,9 +2374,12 @@ L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG mpv0 -----END CERTIFICATE----- -# CN=ISRG Root X1,O=Internet Security Research Group,C=US -# 96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=ISRG Root X1,O=Internet Security Research Group,C=US", + sha256Hash: "96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6", + pem: `-----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 @@ -1904,9 +2410,12 @@ oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- -# CN=ISRG Root X2,O=Internet Security Research Group,C=US -# 69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=ISRG Root X2,O=Internet Security Research Group,C=US", + sha256Hash: "69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470", + pem: `-----BEGIN CERTIFICATE----- MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 @@ -1920,9 +2429,12 @@ zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 /q4AaOeMSQ+2b1tbFfLn -----END CERTIFICATE----- -# CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US -# 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US", + sha256Hash: "5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae", + pem: `-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw @@ -1953,9 +2465,12 @@ l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A 7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H -----END CERTIFICATE----- -# CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US -# 30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US", + sha256Hash: "30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f", + pem: `-----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN @@ -1986,9 +2501,12 @@ tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv 8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- -# CN=Izenpe.com,O=IZENPE S.A.,C=ES -# 2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Izenpe.com,O=IZENPE S.A.,C=ES", + sha256Hash: "2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f", + pem: `-----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD @@ -2022,9 +2540,12 @@ QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- -# CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875 -# 3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875", + sha256Hash: "3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378", + pem: `-----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G @@ -2048,9 +2569,12 @@ tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c 2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW -----END CERTIFICATE----- -# CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US -# 358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US", + sha256Hash: "358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02", + pem: `-----BEGIN CERTIFICATE----- MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw @@ -2065,9 +2589,12 @@ FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= -----END CERTIFICATE----- -# CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US -# c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US", + sha256Hash: "c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0", + pem: `-----BEGIN CERTIFICATE----- MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 @@ -2100,9 +2627,12 @@ dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB RA+GsCyRxj3qrg+E -----END CERTIFICATE----- -# CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR -# 88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR", + sha256Hash: "88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265", + pem: `-----BEGIN CERTIFICATE----- MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 @@ -2135,9 +2665,12 @@ LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul 9XXeifdy -----END CERTIFICATE----- -# CN=NetLock Arany (Class Gold) Főtanúsítvány,OU=Tanúsítványkiadók (Certification Services),O=NetLock Kft.,L=Budapest,C=HU -# 6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=NetLock Arany (Class Gold) Főtanúsítvány,OU=Tanúsítványkiadók (Certification Services),O=NetLock Kft.,L=Budapest,C=HU", + sha256Hash: "6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98", + pem: `-----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl @@ -2161,9 +2694,12 @@ bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- -# CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH -# 6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH", + sha256Hash: "6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6", + pem: `-----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i @@ -2185,9 +2721,12 @@ ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- -# CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH -# 8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH", + sha256Hash: "8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d", + pem: `-----BEGIN CERTIFICATE----- MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg @@ -2202,9 +2741,12 @@ rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV 57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 -----END CERTIFICATE----- -# CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM -# 8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74", + pem: `-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 @@ -2235,9 +2777,12 @@ ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD -----END CERTIFICATE----- -# CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM -# 8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840", + pem: `-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 @@ -2268,9 +2813,12 @@ KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M -----END CERTIFICATE----- -# CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM -# 85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM", + sha256Hash: "85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86", + pem: `-----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV @@ -2303,9 +2851,12 @@ ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y 4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza 8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- -# CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM -# 88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46", + pem: `-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 @@ -2336,9 +2887,12 @@ DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- -# CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM -# 18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM", + sha256Hash: "18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35", + pem: `-----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV @@ -2376,9 +2930,12 @@ Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK 4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- -# CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US -# 22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8", + pem: `-----BEGIN CERTIFICATE----- MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp @@ -2394,9 +2951,12 @@ MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -----END CERTIFICATE----- -# CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US -# 2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c", + pem: `-----BEGIN CERTIFICATE----- MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy @@ -2430,9 +2990,12 @@ w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== -----END CERTIFICATE----- -# CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US -# 3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65", + pem: `-----BEGIN CERTIFICATE----- MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 @@ -2448,9 +3011,12 @@ VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl -----END CERTIFICATE----- -# CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US -# 85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69", + pem: `-----BEGIN CERTIFICATE----- MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp @@ -2484,9 +3050,12 @@ nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY Ic2wBlX7Jz9TkHCpBB5XJ7k= -----END CERTIFICATE----- -# CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US -# c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US", + sha256Hash: "c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143", + pem: `-----BEGIN CERTIFICATE----- MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 @@ -2500,9 +3069,12 @@ uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp 15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== -----END CERTIFICATE----- -# CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US -# 8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US", + sha256Hash: "8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed", + pem: `-----BEGIN CERTIFICATE----- MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX @@ -2534,9 +3106,12 @@ r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU 98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= -----END CERTIFICATE----- -# CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL -# a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL", + sha256Hash: "a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe", + pem: `-----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw @@ -2557,9 +3132,12 @@ oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -----END CERTIFICATE----- -# CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB -# c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB", + sha256Hash: "c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383", + pem: `-----BEGIN CERTIFICATE----- MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN @@ -2573,9 +3151,12 @@ Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q 4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== -----END CERTIFICATE----- -# CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB -# 7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB", + sha256Hash: "7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06", + pem: `-----BEGIN CERTIFICATE----- MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw @@ -2607,9 +3188,12 @@ LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp 0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL -----END CERTIFICATE----- -# CN=Secure Global CA,O=SecureTrust Corporation,C=US -# 4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Secure Global CA,O=SecureTrust Corporation,C=US", + sha256Hash: "4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69", + pem: `-----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx @@ -2631,9 +3215,12 @@ I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- -# CN=SecureSign Root CA12,O=Cybertrust Japan Co.\, Ltd.,C=JP -# 3f034bb5704d44b2d08545a02057de93ebf3905fce721acbc730c06ddaee904e ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SecureSign Root CA12,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "3f034bb5704d44b2d08545a02057de93ebf3905fce721acbc730c06ddaee904e", + pem: `-----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw @@ -2654,9 +3241,12 @@ mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA 55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/ yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== -----END CERTIFICATE----- -# CN=SecureSign Root CA14,O=Cybertrust Japan Co.\, Ltd.,C=JP -# 4b009c1034494f9ab56bba3ba1d62731fc4d20d8955adcec10a925607261e338 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SecureSign Root CA14,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "4b009c1034494f9ab56bba3ba1d62731fc4d20d8955adcec10a925607261e338", + pem: `-----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw @@ -2688,9 +3278,12 @@ Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB 365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c JRNItX+S -----END CERTIFICATE----- -# CN=SecureSign Root CA15,O=Cybertrust Japan Co.\, Ltd.,C=JP -# e778f0f095fe843729cd1a0082179e5314a9c291442805e1fb1d8fb6b8886c3a ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SecureSign Root CA15,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "e778f0f095fe843729cd1a0082179e5314a9c291442805e1fb1d8fb6b8886c3a", + pem: `-----BEGIN CERTIFICATE----- MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy @@ -2704,9 +3297,12 @@ Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT 4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6 bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= -----END CERTIFICATE----- -# CN=SecureTrust CA,O=SecureTrust Corporation,C=US -# f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SecureTrust CA,O=SecureTrust Corporation,C=US", + sha256Hash: "f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73", + pem: `-----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz @@ -2728,9 +3324,12 @@ D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- -# CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\,LTD.,C=JP -# e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\\,LTD.,C=JP", + sha256Hash: "e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11", + pem: `-----BEGIN CERTIFICATE----- MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx @@ -2744,9 +3343,12 @@ BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu 9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= -----END CERTIFICATE----- -# CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US -# 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5", + pem: `-----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs @@ -2769,9 +3371,12 @@ sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- -# CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US -# 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5", + pem: `-----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs @@ -2795,9 +3400,12 @@ iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn 0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN sSi6 -----END CERTIFICATE----- -# CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH -# 62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH", + sha256Hash: "62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95", + pem: `-----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF @@ -2830,9 +3438,12 @@ Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- -# CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE -# 91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE", + sha256Hash: "91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552", + pem: `-----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl @@ -2855,9 +3466,12 @@ g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP BSeOE6Fuwg== -----END CERTIFICATE----- -# CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE -# fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE", + sha256Hash: "fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd", + pem: `-----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl @@ -2880,9 +3494,12 @@ WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p TpPDpFQUWw== -----END CERTIFICATE----- -# CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW -# 3f63bb2814be174ec8b6439cf08d6d56f0b7c405883a5648a334424d6b3ec558 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "3f63bb2814be174ec8b6439cf08d6d56f0b7c405883a5648a334424d6b3ec558", + pem: `-----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290 IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5 @@ -2914,9 +3531,12 @@ NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6 t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X -----END CERTIFICATE----- -# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW -# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b", + pem: `-----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 @@ -2947,9 +3567,12 @@ wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy KwbQBM0= -----END CERTIFICATE----- -# CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW -# bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44", + pem: `-----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz @@ -2970,9 +3593,12 @@ lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- -# CN=Telekom Security TLS ECC Root 2020,O=Deutsche Telekom Security GmbH,C=DE -# 578af4ded0853f4e5998db4aeaf9cbea8d945f60b620a38d1a3c13b2bc7ba8e1 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Telekom Security TLS ECC Root 2020,O=Deutsche Telekom Security GmbH,C=DE", + sha256Hash: "578af4ded0853f4e5998db4aeaf9cbea8d945f60b620a38d1a3c13b2bc7ba8e1", + pem: `-----BEGIN CERTIFICATE----- MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw @@ -2987,9 +3613,12 @@ MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn 27iQ7t0l -----END CERTIFICATE----- -# CN=Telekom Security TLS RSA Root 2023,O=Deutsche Telekom Security GmbH,C=DE -# efc65cadbb59adb6efe84da22311b35624b71b3b1ea0da8b6655174ec8978646 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Telekom Security TLS RSA Root 2023,O=Deutsche Telekom Security GmbH,C=DE", + sha256Hash: "efc65cadbb59adb6efe84da22311b35624b71b3b1ea0da8b6655174ec8978646", + pem: `-----BEGIN CERTIFICATE----- MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy @@ -3022,9 +3651,12 @@ X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= -----END CERTIFICATE----- -# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI -# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI", + sha256Hash: "242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c", + pem: `-----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 @@ -3056,9 +3688,12 @@ VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA rBPuUBQemMc= -----END CERTIFICATE----- -# CN=TeliaSonera Root CA v1,O=TeliaSonera -# dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TeliaSonera Root CA v1,O=TeliaSonera", + sha256Hash: "dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389", + pem: `-----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD @@ -3088,9 +3723,12 @@ t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -# CN=TrustAsia Global Root CA G3,O=TrustAsia Technologies\, Inc.,C=CN -# e0d3226aeb1163c2e48ff9be3b50b4c6431be7bb1eacc5c36b5d5ec509039a08 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TrustAsia Global Root CA G3,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "e0d3226aeb1163c2e48ff9be3b50b4c6431be7bb1eacc5c36b5d5ec509039a08", + pem: `-----BEGIN CERTIFICATE----- MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe @@ -3123,9 +3761,12 @@ gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV +Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo FGWsJwt0ivKH -----END CERTIFICATE----- -# CN=TrustAsia Global Root CA G4,O=TrustAsia Technologies\, Inc.,C=CN -# be4b56cb5056c0136a526df444508daa36a0b54f42e4ac38f72af470e479654c ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TrustAsia Global Root CA G4,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "be4b56cb5056c0136a526df444508daa36a0b54f42e4ac38f72af470e479654c", + pem: `-----BEGIN CERTIFICATE----- MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y @@ -3140,9 +3781,12 @@ AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj /bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== -----END CERTIFICATE----- -# CN=Trustwave Global Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -# 97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Trustwave Global Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8", + pem: `-----BEGIN CERTIFICATE----- MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 @@ -3176,9 +3820,12 @@ h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK yeC2nOnOcXHebD8WpHk= -----END CERTIFICATE----- -# CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -# 945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4", + pem: `-----BEGIN CERTIFICATE----- MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 @@ -3193,9 +3840,12 @@ DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 -----END CERTIFICATE----- -# CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -# 55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097", + pem: `-----BEGIN CERTIFICATE----- MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 @@ -3212,9 +3862,12 @@ AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu Sw== -----END CERTIFICATE----- -# CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN -# 2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN", + sha256Hash: "2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41", + pem: `-----BEGIN CERTIFICATE----- MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv @@ -3247,9 +3900,12 @@ CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= -----END CERTIFICATE----- -# CN=UCA Extended Validation Root,O=UniTrust,C=CN -# d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=UCA Extended Validation Root,O=UniTrust,C=CN", + sha256Hash: "d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24", + pem: `-----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx @@ -3280,9 +3936,12 @@ xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax -----END CERTIFICATE----- -# CN=UCA Global G2 Root,O=UniTrust,C=CN -# 9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=UCA Global G2 Root,O=UniTrust,C=CN", + sha256Hash: "9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c", + pem: `-----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x @@ -3313,9 +3972,12 @@ DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX UB+K+wb1whnw0A== -----END CERTIFICATE----- -# CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US -# 4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US", + sha256Hash: "4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a", + pem: `-----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT @@ -3331,9 +3993,12 @@ VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- -# CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US -# e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US", + sha256Hash: "e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2", + pem: `-----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV @@ -3367,9 +4032,12 @@ VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG jjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- -# CN=XRamp Global Certification Authority,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,C=US -# cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=XRamp Global Certification Authority,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,C=US", + sha256Hash: "cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2", + pem: `-----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY @@ -3394,9 +4062,12 @@ IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ O+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- -# CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937 -# beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937", + sha256Hash: "beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99", + pem: `-----BEGIN CERTIFICATE----- MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv @@ -3411,9 +4082,12 @@ eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ +efcMQ== -----END CERTIFICATE----- -# CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US -# bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US", + sha256Hash: "bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3", + pem: `-----BEGIN CERTIFICATE----- MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw @@ -3427,9 +4101,12 @@ Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c 3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J 0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== -----END CERTIFICATE----- -# CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN -# 86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN", + sha256Hash: "86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b", + pem: `-----BEGIN CERTIFICATE----- MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g @@ -3444,9 +4121,12 @@ hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD +JbNR6iC8hZVdyR+EhCVBCyj -----END CERTIFICATE----- -# CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US -# 125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US", + sha256Hash: "125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f", + pem: `-----BEGIN CERTIFICATE----- MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw @@ -3467,9 +4147,12 @@ YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT +xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= -----END CERTIFICATE----- -# CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN -# 40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN", + sha256Hash: "40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367", + pem: `-----BEGIN CERTIFICATE----- MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH @@ -3491,9 +4174,12 @@ GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx iN66zB+Afko= -----END CERTIFICATE----- -# CN=vTrus ECC Root CA,O=iTrusChina Co.\,Ltd.,C=CN -# 30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=vTrus ECC Root CA,O=iTrusChina Co.\\,Ltd.,C=CN", + sha256Hash: "30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3", + pem: `-----BEGIN CERTIFICATE----- MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz @@ -3507,9 +4193,12 @@ V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG GJTO -----END CERTIFICATE----- -# CN=vTrus Root CA,O=iTrusChina Co.\,Ltd.,C=CN -# 8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "CN=vTrus Root CA,O=iTrusChina Co.\\,Ltd.,C=CN", + sha256Hash: "8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387", + pem: `-----BEGIN CERTIFICATE----- MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx @@ -3540,9 +4229,12 @@ UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= -----END CERTIFICATE----- -# OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES -# ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES", + sha256Hash: "ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa", + pem: `-----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ @@ -3574,9 +4266,12 @@ fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -----END CERTIFICATE----- -# OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\, Inc.,C=US -# c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\\, Inc.,C=US", + sha256Hash: "c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4", + pem: `-----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 @@ -3600,9 +4295,12 @@ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- -# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP -# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\\,LTD.,C=JP", + sha256Hash: "513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6", + pem: `-----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX @@ -3623,9 +4321,12 @@ t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy 1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- -# OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US -# 1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\\, Inc.,C=US", + sha256Hash: "1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658", + pem: `-----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw @@ -3649,9 +4350,12 @@ xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- -# OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO -# 657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO", + sha256Hash: "657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305", + pem: `-----BEGIN CERTIFICATE----- MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ @@ -3682,9 +4386,12 @@ PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE 1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX QRBdJ3NghVdJIgc= -----END CERTIFICATE----- -# OU=certSIGN ROOT CA,O=certSIGN,C=RO -# eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=certSIGN ROOT CA,O=certSIGN,C=RO", + sha256Hash: "eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb", + pem: `-----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP @@ -3704,9 +4411,12 @@ Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 9u6wWk5JRFRYX0KD -----END CERTIFICATE----- -# OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\, Ltd.,C=TW -# c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\\, Ltd.,C=TW", + sha256Hash: "c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5", + pem: `-----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe @@ -3739,9 +4449,12 @@ Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D hNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- -# SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES -# fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599 ------BEGIN CERTIFICATE----- +`, + }, + { + cn: "SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES", + sha256Hash: "fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599", + pem: `-----BEGIN CERTIFICATE----- MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV @@ -3775,4 +4488,6 @@ OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= -----END CERTIFICATE----- -` +`, + }, +} diff --git a/x/crypto/x509roots/fallback/bundle.go.orig b/x/crypto/x509roots/fallback/bundle.go.orig new file mode 100644 index 00000000000..89d97ba0910 --- /dev/null +++ b/x/crypto/x509roots/fallback/bundle.go.orig @@ -0,0 +1,3776 @@ +// Code generated by gen_fallback_bundle.go; DO NOT EDIT. + +package fallback + +import "crypto/x509" +import "encoding/pem" + +func mustParse(b []byte) []*x509.Certificate { + var roots []*x509.Certificate + for len(b) > 0 { + var block *pem.Block + block, b = pem.Decode(b) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + panic("unexpected PEM block type: " + block.Type) + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic(err) + } + roots = append(roots, cert) + } + return roots +} + +var bundle = mustParse([]byte(pemRoots)) + +// Format of the PEM list is: +// * Subject common name +// * SHA256 hash +// * PEM block + +const pemRoots = ` +# CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- +# CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a +# 554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- +# CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES +# 9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- +# CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT +# 55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- +# CN=Amazon Root CA 1,O=Amazon,C=US +# 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- +# CN=Amazon Root CA 2,O=Amazon,C=US +# 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- +# CN=Amazon Root CA 3,O=Amazon,C=US +# 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- +# CN=Amazon Root CA 4,O=Amazon,C=US +# e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- +# CN=Atos TrustedRoot 2011,O=Atos,C=DE +# f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- +# CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE +# b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8 +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w +LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w +CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 +MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF +Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X +tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 +AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 +KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD +aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu +CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo +9H1/IISpQuQo +-----END CERTIFICATE----- +# CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE +# 81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM +MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx +MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 +MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD +QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z +4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv +Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ +kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs +GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln +nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh +3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD +0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy +geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 +ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB +c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI +pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs +o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ +qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw +xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM +rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 +AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR +0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY +o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 +dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE +oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- +# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES +# 57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 +MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc +tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd +IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC +AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw +ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m +iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF +Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ +hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P +Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE +EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV +1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t +CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR +5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw +f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 +ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK +GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- +# CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN +# f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU +MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI +T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz +MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF +SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh +bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z +xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ +spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 +58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR +at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll +5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq +nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK +V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ +pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO +z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn +jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ +WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF +7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli +awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u ++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 +X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN +SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo +P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI ++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz +znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 +eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 +YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy +r/6zcCwupvI= +-----END CERTIFICATE----- +# CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN +# 574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882 +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw +CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ +VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy +MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ +TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS +b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B +IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ ++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK +sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA +94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B +43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- +# CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE +# 16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- +# CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO +# 9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- +# CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO +# edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- +# CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK +# e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- +# CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN +# 5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- +# CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# 0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- +# CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# 1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- +# CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB +# 52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- +# CN=Certainly Root E1,O=Certainly,C=US +# b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2 +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu +bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ +BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s +eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK ++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 +QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 +hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm +ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG +BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- +# CN=Certainly Root R1,O=Certainly,C=US +# 77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw +PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy +dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 +YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 +1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT +vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed +aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 +1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 +r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 +cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ +wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ +6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA +2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH +Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR +eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u +d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr +PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi +1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd +rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di +taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 +lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj +yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn +Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy +yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n +wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 +OV+KmalBWQewLK8= +-----END CERTIFICATE----- +# CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR +# d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- +# CN=Certigna,O=Dhimyotis,C=FR +# e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- +# CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL +# 6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6 +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- +# CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL +# b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- +# CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL +# 5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- +# CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL +# fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd +-----BEGIN CERTIFICATE----- +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 +MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu +MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV +BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw +MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg +U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ +n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q +p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq +NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF +8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3 +HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa +mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi +7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF +ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P +qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ +v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6 +Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD +ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4 +WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo +zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR +5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ +GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf +5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq +0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D +P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM +qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP +0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf +E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE----- +# CN=CommScope Public Trust ECC Root-01,O=CommScope,C=US +# 11437cda7bb45e41365f45b39a38986b0de00def348e0c7bb0873633800bc38b +-----BEGIN CERTIFICATE----- +MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa +Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C +flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE +hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq +hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg +2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS +Um9poIyNStDuiw7LR47QjRE= +-----END CERTIFICATE----- +# CN=CommScope Public Trust ECC Root-02,O=CommScope,C=US +# 2ffb7f813bbbb3c89ab4e8162d0f16d71509a830cc9d73c262e5140875d1ad4a +-----BEGIN CERTIFICATE----- +MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa +Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL +j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU +v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq +hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n +ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV +mkzw5l4lIhVtwodZ0LKOag== +-----END CERTIFICATE----- +# CN=CommScope Public Trust RSA Root-01,O=CommScope,C=US +# 02bdf96e2a45dd9bf18fc7e1dbdf21a0379ba3c9c2610344cfd8d606fec1ed81 +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1 +NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk +YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh +suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al +DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj +WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl +P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547 +KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p +UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/ +kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO +Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB +Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U +CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ +KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 +NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ +nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+ +QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v +trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a +aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD +j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4 +Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w +lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn +YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc +icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw +-----END CERTIFICATE----- +# CN=CommScope Public Trust RSA Root-02,O=CommScope,C=US +# ffe943d793424b4f7c440c1c3d648d5363f34b82dc87aa7a9f118fc5dee101f1 +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2 +NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE +NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0 +kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C +rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz +hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2 +LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs +n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku +FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5 +kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3 +wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v +wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs +5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ +KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB +KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3 ++VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme +APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq +pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT +6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF +sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt +PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d +lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670 +v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O +rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 +-----END CERTIFICATE----- +# CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE +# e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044 +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 +NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS +zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 +QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ +VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW +wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV +dWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- +# CN=D-TRUST BR Root CA 2 2023,O=D-Trust GmbH,C=DE +# 0552e6f83fdf65e8fa9670e666df28a4e21340b510cbe52566f97c4fb94b2bd1 +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI +MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE +LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw +OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi +MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr +i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE +gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8 +k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT +Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl +2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U +cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP +/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS +uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+ +0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N +DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+ +XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61 +GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI +FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n +riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR +VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc +LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn +4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD +hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG +koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46 +ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS +Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 +knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ +hJ65bvspmZDogNOfJA== +-----END CERTIFICATE----- +# CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE +# 08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 +NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC +/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD +wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 +OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA +y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb +gfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- +# CN=D-TRUST EV Root CA 2 2023,O=D-Trust GmbH,C=DE +# 8e8221b2e7d4007836a1672f0dcc299c33bc07d316f132fa1a206d587150f1ce +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI +MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE +LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw +OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi +MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK +F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE +7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe +EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6 +lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb +RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV +jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc +jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx +TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ +ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk +hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF +NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH +kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14 +QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4 +pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q +3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU +t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX +cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8 +ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT +2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs +7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP +gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst +Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh +XBxvWHZks/wCuPWdCg== +-----END CERTIFICATE----- +# CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE +# 49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- +# CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE +# eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- +# CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# 3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- +# CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US +# 7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- +# CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US +# 7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- +# CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# 4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- +# CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US +# cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- +# CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US +# 31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- +# CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- +# CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US +# 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp +Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 +MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS +7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp +0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS +B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ +LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 +DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- +# CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US +# 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT +HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN +NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs +IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ +ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 +2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp +wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM +pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD +nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po +sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx +Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd +Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX +KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe +XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL +tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv +TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H +PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF +O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ +REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik +AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv +/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ +p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw +MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF +qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK +ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- +# CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US +# 552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- +# CN=FIRMAPROFESIONAL CA ROOT-A WEB,O=Firmaprofesional SA,C=ES,2.5.4.97=#130f56415445532d413632363334303638 +# bef256daf26e9c69bdec1602359798f3caf71821a03e018257c53c65617f3d4a +-----BEGIN CERTIFICATE----- +MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw +CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE +YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB +IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw +CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE +YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB +IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf +e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C +cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O +BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw +hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG +XSaQpYXFuXqUPoeovQA= +-----END CERTIFICATE----- +# CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\,LTD.,C=CN +# bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- +# CN=GTS Root R1,O=Google Trust Services LLC,C=US +# d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c +-----END CERTIFICATE----- +# CN=GTS Root R2,O=Google Trust Services LLC,C=US +# 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- +# CN=GTS Root R3,O=Google Trust Services LLC,C=US +# 34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48 +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G +jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 +4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 +VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm +ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X +-----END CERTIFICATE----- +# CN=GTS Root R4,O=Google Trust Services LLC,C=US +# 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- +# CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE +# ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- +# CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE +# cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- +# CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE +# 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- +# CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign +# b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2 +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD +VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw +MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g +UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx +uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV +HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ ++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 +bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- +# CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign +# 179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- +# CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign +# cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- +# CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign +# 2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- +# CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\, Inc.,L=Scottsdale,ST=Arizona,C=US +# 45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- +# CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR +# 3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401 +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw +CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh +cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v +dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG +A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 +KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y +STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD +AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw +SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN +nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- +# CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR +# d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg +Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL +MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l +mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE +4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv +a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M +pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw +Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b +LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY +AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB +AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq +E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr +W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ +CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU +X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 +f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja +H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP +JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P +zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt +jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 +/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT +BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 +aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW +xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU +63ZTGI0RmLo= +-----END CERTIFICATE----- +# CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR +# 44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- +# CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR +# a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- +# CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\, Ltd.,C=TW +# f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa +Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 +YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw +qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv +Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 +lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz +Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ +KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK +FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj +HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr +y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ +/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM +a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 +fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG +SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc +SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza +ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc +XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg +iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho +L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF +Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr +kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ +vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU +YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- +# CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK +# 5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6 +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL +BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ +SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n +a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5 +NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT +CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u +Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO +dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI +VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV +9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY +2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY +vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt +bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb +x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+ +l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK +TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj +Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw +DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG +7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk +MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr +gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk +GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS +3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm +Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+ +l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c +JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP +L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa +LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG +mpv0 +-----END CERTIFICATE----- +# CN=ISRG Root X1,O=Internet Security Research Group,C=US +# 96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- +# CN=ISRG Root X2,O=Internet Security Research Group,C=US +# 69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470 +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw +CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg +R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 +MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT +ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW ++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 +ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI +zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW +tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 +/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- +# CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US +# 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- +# CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US +# 30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- +# CN=Izenpe.com,O=IZENPE S.A.,C=ES +# 2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- +# CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875 +# 3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- +# CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US +# 358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02 +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD +VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy +b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR +ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb +hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 +FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV +L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB +iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- +# CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US +# c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0 +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl +MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N +aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ +Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 +ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 +HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm +gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ +jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc +aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG +YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 +W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K +UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH ++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q +W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC +LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC +gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 +tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh +SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 +TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 +pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR +xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp +GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 +dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN +AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB +RA+GsCyRxj3qrg+E +-----END CERTIFICATE----- +# CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR +# 88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265 +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- +# CN=NetLock Arany (Class Gold) Főtanúsítvány,OU=Tanúsítványkiadók (Certification Services),O=NetLock Kft.,L=Budapest,C=HU +# 6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- +# CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH +# 6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- +# CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH +# 8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- +# CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM +# 8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- +# CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM +# 8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- +# CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM +# 85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- +# CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM +# 88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- +# CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM +# 18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- +# CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US +# 22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- +# CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US +# 2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- +# CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US +# 3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- +# CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US +# 85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- +# CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US +# c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143 +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT +U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 +MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh +dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm +acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN +SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW +uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp +15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN +b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== +-----END CERTIFICATE----- +# CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US +# 8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD +DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX +DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP +L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY +t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins +S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 +PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO +L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 +R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w +dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS ++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS +d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG +AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f +gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z +NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM +QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf +R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ +DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW +P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy +lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq +bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w +AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q +r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji +Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU +98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- +# CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL +# a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- +# CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB +# c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383 +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN +MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG +A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC +WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ +6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B +Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa +qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q +4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== +-----END CERTIFICATE----- +# CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB +# 7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06 +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD +Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw +HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY +MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp +YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa +ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz +SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf +iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X +ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 +IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS +VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE +SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu ++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt +8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L +HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt +zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ +YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 +gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA +Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB +JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX +DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui +TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 +dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 +LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp +0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY +QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- +# CN=Secure Global CA,O=SecureTrust Corporation,C=US +# 4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- +# CN=SecureSign Root CA12,O=Cybertrust Japan Co.\, Ltd.,C=JP +# 3f034bb5704d44b2d08545a02057de93ebf3905fce721acbc730c06ddaee904e +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u +LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw +NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD +eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS +b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF +KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt +p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd +J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur +FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J +hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K +h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF +AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld +mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ +mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA +8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV +55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/ +yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== +-----END CERTIFICATE----- +# CN=SecureSign Root CA14,O=Cybertrust Japan Co.\, Ltd.,C=JP +# 4b009c1034494f9ab56bba3ba1d62731fc4d20d8955adcec10a925607261e338 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM +BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u +LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw +NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD +eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS +b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/ +FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg +vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy +6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo +/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J +kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ +0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib +y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac +18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs +0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB +SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL +ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk +86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E +rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib +ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT +zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS +DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4 +2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo +FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy +K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6 +dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl +Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB +365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c +JRNItX+S +-----END CERTIFICATE----- +# CN=SecureSign Root CA15,O=Cybertrust Japan Co.\, Ltd.,C=JP +# e778f0f095fe843729cd1a0082179e5314a9c291442805e1fb1d8fb6b8886c3a +-----BEGIN CERTIFICATE----- +MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw +UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM +dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy +NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl +cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290 +IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4 +wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR +ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT +9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp +4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6 +bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= +-----END CERTIFICATE----- +# CN=SecureTrust CA,O=SecureTrust Corporation,C=US +# f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- +# CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\,LTD.,C=JP +# e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11 +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT +AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD +VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx +NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT +HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 +IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl +dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK +ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu +9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O +be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= +-----END CERTIFICATE----- +# CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- +# CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- +# CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH +# 62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95 +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- +# CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# 91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- +# CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE +# fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- +# CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW +# 3f63bb2814be174ec8b6439cf08d6d56f0b7c405883a5648a334424d6b3ec558 +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ +MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290 +IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5 +WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO +LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P +40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF +avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/ +34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i +JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu +j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf +Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP +2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA +S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA +oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC +kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW +5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd +BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB +AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t +tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn +68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn +TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t +RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx +f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI +Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz +8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4 +NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX +xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6 +t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X +-----END CERTIFICATE----- +# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW +# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- +# CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW +# bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- +# CN=Telekom Security TLS ECC Root 2020,O=Deutsche Telekom Security GmbH,C=DE +# 578af4ded0853f4e5998db4aeaf9cbea8d945f60b620a38d1a3c13b2bc7ba8e1 +-----BEGIN CERTIFICATE----- +MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw +CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH +bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw +MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx +JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE +AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O +tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP +f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA +MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di +z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn +27iQ7t0l +-----END CERTIFICATE----- +# CN=Telekom Security TLS RSA Root 2023,O=Deutsche Telekom Security GmbH,C=DE +# efc65cadbb59adb6efe84da22311b35624b71b3b1ea0da8b6655174ec8978646 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj +MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 +eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy +MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC +REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG +A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9 +cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV +cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA +U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6 +Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug +BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy +8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J +co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg +8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8 +rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12 +mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg ++y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX +gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 +p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ +pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm +9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw +M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd +GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+ +CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t +xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+ +w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK +L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj +X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q +ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm +dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= +-----END CERTIFICATE----- +# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI +# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx +CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE +AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 +NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ +MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq +AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 +vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 +lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD +n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT +7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o +6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC +TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 +WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R +DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI +pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj +YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy +rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi +0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM +A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS +SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K +TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF +6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er +3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt +Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT +VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW +ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA +rBPuUBQemMc= +-----END CERTIFICATE----- +# CN=TeliaSonera Root CA v1,O=TeliaSonera +# dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- +# CN=TrustAsia Global Root CA G3,O=TrustAsia Technologies\, Inc.,C=CN +# e0d3226aeb1163c2e48ff9be3b50b4c6431be7bb1eacc5c36b5d5ec509039a08 +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM +BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp +ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe +Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw +IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU +cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS +T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK +AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 +nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep +qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA +yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs +hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX +zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv +kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT +f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA +uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB +o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih +MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E +BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 +wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 +XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 +JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j +ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV +VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx +xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on +AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d +7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj +gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV ++Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo +FGWsJwt0ivKH +-----END CERTIFICATE----- +# CN=TrustAsia Global Root CA G4,O=TrustAsia Technologies\, Inc.,C=CN +# be4b56cb5056c0136a526df444508daa36a0b54f42e4ac38f72af470e479654c +-----BEGIN CERTIFICATE----- +MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw +WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y +MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD +VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz +dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx +s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw +LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD +pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE +AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR +UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj +/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== +-----END CERTIFICATE----- +# CN=Trustwave Global Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US +# 97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8 +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw +CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x +ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 +c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx +OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI +SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn +swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu +7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 +1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW +80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP +JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l +RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw +hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 +coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc +BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n +twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W +0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe +uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q +lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB +aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE +sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT +MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe +qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh +VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 +h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 +EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK +yeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- +# CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US +# 945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4 +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN +FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w +DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw +CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh +DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- +# CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US +# 55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097 +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ +j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF +1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G +A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 +AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC +MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu +Sw== +-----END CERTIFICATE----- +# CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN +# 2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg +Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv +b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG +EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u +IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ +n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd +2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF +VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ +GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF +li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU +r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 +eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb +MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg +jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB +7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW +5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE +ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z +xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu +QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 +FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH +22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP +xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn +dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 +Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b +nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ +CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH +u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj +d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- +# CN=UCA Extended Validation Root,O=UniTrust,C=CN +# d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- +# CN=UCA Global G2 Root,O=UniTrust,C=CN +# 9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- +# CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US +# 4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- +# CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US +# e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- +# CN=XRamp Global Certification Authority,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,C=US +# cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- +# CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937 +# beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99 +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV +BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk +LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv +b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ +BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg +THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v +IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv +xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H +Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB +eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo +jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ ++efcMQ== +-----END CERTIFICATE----- +# CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US +# bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3 +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- +# CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN +# 86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- +# CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US +# 125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- +# CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN +# 40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367 +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- +# CN=vTrus ECC Root CA,O=iTrusChina Co.\,Ltd.,C=CN +# 30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3 +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw +RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY +BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz +MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u +LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 +v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd +e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw +V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA +AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG +GJTO +-----END CERTIFICATE----- +# CN=vTrus Root CA,O=iTrusChina Co.\,Ltd.,C=CN +# 8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387 +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL +BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x +FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx +MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s +THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc +IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU +AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ +GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 +8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH +flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt +J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim +0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN +pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ +UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW +OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB +AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet +8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j +bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM +Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv +TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS +S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr +I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 +b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB +UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P +Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven +sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= +-----END CERTIFICATE----- +# OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES +# ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- +# OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\, Inc.,C=US +# c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- +# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP +# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- +# OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US +# 1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- +# OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO +# 657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g +Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ +BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ +R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF +dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw +vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ +uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp +n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs +cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW +xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P +rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF +DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx +DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy +LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C +eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ +d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq +kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl +qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 +OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c +NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk +ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO +pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj +03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk +PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE +1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX +QRBdJ3NghVdJIgc= +-----END CERTIFICATE----- +# OU=certSIGN ROOT CA,O=certSIGN,C=RO +# eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- +# OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\, Ltd.,C=TW +# c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- +# SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES +# fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599 +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV +BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk +YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV +BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN +MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF +UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD +VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v +dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj +cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q +yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH +2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX +H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL +zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR +p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz +W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/ +SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn +LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3 +n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B +u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L +9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej +rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK +pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0 +vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq +OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ +/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9 +2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI ++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2 +MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo +tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE----- +` diff --git a/x/crypto/x509roots/fallback/fallback.go b/x/crypto/x509roots/fallback/fallback.go index c0c1bae776f..31514c55d8a 100644 --- a/x/crypto/x509roots/fallback/fallback.go +++ b/x/crypto/x509roots/fallback/fallback.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.20 - // Package fallback embeds a set of fallback X.509 trusted roots in the // application by automatically invoking [x509.SetFallbackRoots]. This allows // the application to work correctly even if the operating system does not @@ -24,8 +22,19 @@ import "github.com/runZeroInc/excrypto/crypto/x509" func init() { p := x509.NewCertPool() - for _, c := range bundle { - p.AddCert(c) + for _, c := range parsedCertificates { + if len(c.constraints) == 0 { + p.AddCert(c.cert) + } else { + p.AddCertWithConstraint(c.cert, func(chain []*x509.Certificate) error { + for _, constraint := range c.constraints { + if err := constraint(chain); err != nil { + return err + } + } + return nil + }) + } } x509.SetFallbackRoots(p) } diff --git a/x/crypto/x509roots/fallback/fallback.go.orig b/x/crypto/x509roots/fallback/fallback.go.orig new file mode 100644 index 00000000000..42717e1cd41 --- /dev/null +++ b/x/crypto/x509roots/fallback/fallback.go.orig @@ -0,0 +1,29 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fallback embeds a set of fallback X.509 trusted roots in the +// application by automatically invoking [x509.SetFallbackRoots]. This allows +// the application to work correctly even if the operating system does not +// provide a verifier or system roots pool. +// +// To use it, import the package like +// +// import _ "golang.org/x/crypto/x509roots/fallback" +// +// It's recommended that only binaries, and not libraries, import this package. +// +// This package must be kept up to date for security and compatibility reasons. +// Use govulncheck to be notified of when new versions of the package are +// available. +package fallback + +import "crypto/x509" + +func init() { + p := x509.NewCertPool() + for _, c := range bundle { + p.AddCert(c) + } + x509.SetFallbackRoots(p) +} diff --git a/x/crypto/x509roots/gen_fallback_bundle.go b/x/crypto/x509roots/gen_fallback_bundle.go index af7850ca884..fcd2951a08d 100644 --- a/x/crypto/x509roots/gen_fallback_bundle.go +++ b/x/crypto/x509roots/gen_fallback_bundle.go @@ -20,6 +20,7 @@ import ( "net/http" "os" "sort" + "time" "github.com/runZeroInc/excrypto/crypto/sha256" @@ -28,40 +29,70 @@ import ( const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT. -//go:build go1.20 - package fallback -import "github.com/runZeroInc/excrypto/crypto/x509" -import "encoding/pem" +import ( + "github.com/runZeroInc/excrypto/crypto/x509" + "github.com/runZeroInc/excrypto/encoding/pem" + "fmt" + "time" +) + +type unparsedCertificate struct { + cn string + sha256Hash string + pem string + + // possible constraints + distrustAfter string +} + +type parsedCertificate struct { + cert *x509.Certificate + constraints []func([]*x509.Certificate) error +} -func mustParse(b []byte) []*x509.Certificate { - var roots []*x509.Certificate - for len(b) > 0 { - var block *pem.Block - block, b = pem.Decode(b) +func mustParse(unparsedCerts []unparsedCertificate) []parsedCertificate { + var b []parsedCertificate + for _, unparsed := range unparsedCerts { + block, rest := pem.Decode([]byte(unparsed.pem)) if block == nil { - break + panic(fmt.Sprintf("unexpected nil PEM block for %q", unparsed.cn)) + } + if len(rest) != 0 { + panic(fmt.Sprintf("unexpected trailing data in PEM for %q", unparsed.cn)) } if block.Type != "CERTIFICATE" { - panic("unexpected PEM block type: " + block.Type) + panic(fmt.Sprintf("unexpected PEM block type for %q: %s", unparsed.cn, block.Type)) } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { panic(err) } - roots = append(roots, cert) + parsed := parsedCertificate{cert: cert} + // parse possible constraints, this should check all fields of unparsedCertificate. + if unparsed.distrustAfter != "" { + distrustAfter, err := time.Parse(time.RFC3339, unparsed.distrustAfter) + if err != nil { + panic(fmt.Sprintf("failed to parse distrustAfter %q: %s", unparsed.distrustAfter, err)) + } + parsed.constraints = append(parsed.constraints, func(chain []*x509.Certificate) error { + for _, c := range chain { + if c.NotBefore.After(distrustAfter) { + return fmt.Errorf("certificate issued after distrust-after date %q", distrustAfter) + } + } + return nil + }) + } + b = append(b, parsed) } - return roots + return b } -var bundle = mustParse([]byte(pemRoots)) - -// Format of the PEM list is: -// * Subject common name -// * SHA256 hash -// * PEM block +var parsedCertificates = mustParse(unparsedCertificates) +var unparsedCertificates = []unparsedCertificate{ ` var ( @@ -125,19 +156,33 @@ func main() { b := new(bytes.Buffer) b.WriteString(tmpl) - fmt.Fprintln(b, "const pemRoots = `") for _, c := range certs { - if len(c.Constraints) > 0 { - // Until the constrained roots API lands, skip anything that has any - // additional constraints. Once that API is available, we can add - // build constraints that support both the current version and the - // new version. + var constraints []string + var skip bool + for _, constraint := range c.Constraints { + switch t := constraint.(type) { + case nss.DistrustAfter: + constraints = append(constraints, fmt.Sprintf("distrustAfter: \"%s\",", time.Time(t).Format(time.RFC3339))) + default: + // If we encounter any constraints we don't support, skip the certificate. + skip = true + break + } + } + if skip { continue } - fmt.Fprintf(b, "# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw)) - pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw}) + fmt.Fprintf(b, "{\ncn: %q,\nsha256Hash: \"%x\",\npem: `%s`,\n", + c.X509.Subject.String(), + sha256.Sum256(c.X509.Raw), + string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw})), + ) + for _, constraint := range constraints { + fmt.Fprintln(b, constraint) + } + fmt.Fprintln(b, "},") } - fmt.Fprintln(b, "`") + fmt.Fprintln(b, "}") formatted, err := format.Source(b.Bytes()) if err != nil { diff --git a/x/crypto/x509roots/gen_fallback_bundle.go.orig b/x/crypto/x509roots/gen_fallback_bundle.go.orig new file mode 100644 index 00000000000..246f60ca9b7 --- /dev/null +++ b/x/crypto/x509roots/gen_fallback_bundle.go.orig @@ -0,0 +1,147 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build generate + +//go:generate go run gen_fallback_bundle.go + +package main + +import ( + "bytes" + "crypto/sha256" + "encoding/pem" + "flag" + "fmt" + "go/format" + "io" + "log" + "mime" + "net/http" + "os" + "sort" + + "golang.org/x/crypto/x509roots/nss" +) + +const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT. + +package fallback + +import "crypto/x509" +import "encoding/pem" + +func mustParse(b []byte) []*x509.Certificate { + var roots []*x509.Certificate + for len(b) > 0 { + var block *pem.Block + block, b = pem.Decode(b) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + panic("unexpected PEM block type: " + block.Type) + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic(err) + } + roots = append(roots, cert) + } + return roots +} + +var bundle = mustParse([]byte(pemRoots)) + +// Format of the PEM list is: +// * Subject common name +// * SHA256 hash +// * PEM block + +` + +var ( + certDataURL = flag.String("certdata-url", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "URL to the raw certdata.txt file to parse (certdata-path overrides this, if provided)") + certDataPath = flag.String("certdata-path", "", "Path to the NSS certdata.txt file to parse (this overrides certdata-url, if provided)") + output = flag.String("output", "fallback/bundle.go", "Path to file to write output to") +) + +func main() { + flag.Parse() + + var certdata io.Reader + + if *certDataPath != "" { + f, err := os.Open(*certDataPath) + if err != nil { + log.Fatalf("unable to open %q: %s", *certDataPath, err) + } + defer f.Close() + certdata = f + } else { + resp, err := http.Get(*certDataURL) + if err != nil { + log.Fatalf("failed to request %q: %s", *certDataURL, err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(io.LimitReader(resp.Body, 4<<10)) + log.Fatalf("got non-200 OK status code: %v body: %q", resp.Status, body) + } else if ct, want := resp.Header.Get("Content-Type"), `text/plain; charset="UTF-8"`; ct != want { + if mediaType, _, err := mime.ParseMediaType(ct); err != nil { + log.Fatalf("bad Content-Type header %q: %v", ct, err) + } else if mediaType != "text/plain" { + log.Fatalf("got media type %q, want %q", mediaType, "text/plain") + } + } + certdata = resp.Body + } + + certs, err := nss.Parse(certdata) + if err != nil { + log.Fatalf("failed to parse %q: %s", *certDataPath, err) + } + + if len(certs) == 0 { + log.Fatal("certdata.txt appears to contain zero roots") + } + + sort.Slice(certs, func(i, j int) bool { + // Sort based on the stringified subject (which may not be unique), and + // break any ties by just sorting on the raw DER (which will be unique, + // but is expensive). This should produce a stable sorting, which should + // be mostly readable by a human looking for a specific root or set of + // roots. + subjI, subjJ := certs[i].X509.Subject.String(), certs[j].X509.Subject.String() + if subjI == subjJ { + return string(certs[i].X509.Raw) < string(certs[j].X509.Raw) + } + return subjI < subjJ + }) + + b := new(bytes.Buffer) + b.WriteString(tmpl) + fmt.Fprintln(b, "const pemRoots = `") + for _, c := range certs { + if len(c.Constraints) > 0 { + // Until the constrained roots API lands, skip anything that has any + // additional constraints. Once that API is available, we can add + // build constraints that support both the current version and the + // new version. + continue + } + fmt.Fprintf(b, "# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw)) + pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw}) + } + fmt.Fprintln(b, "`") + + formatted, err := format.Source(b.Bytes()) + if err != nil { + log.Fatalf("failed to format source: %s", err) + } + + if err := os.WriteFile(*output, formatted, 0644); err != nil { + log.Fatalf("failed to write to %q: %s", *output, err) + } +}