github.com/filosottile/go@v0.0.0-20170906193555-dbed9972d994/src/crypto/tls/ktls.go (about) 1 package tls 2 3 import ( 4 "log" 5 "net" 6 "syscall" 7 "unsafe" 8 ) 9 10 // https://github.com/torvalds/linux/blob/v4.13/Documentation/networking/tls.txt 11 12 const ( 13 TCP_ULP = 31 14 SOL_TLS = 282 15 TLS_TX = 1 16 17 kTLS_CIPHER_AES_GCM_128 = 51 18 kTLS_CIPHER_AES_GCM_128_IV_SIZE = 8 19 kTLS_CIPHER_AES_GCM_128_KEY_SIZE = 16 20 kTLS_CIPHER_AES_GCM_128_SALT_SIZE = 4 21 kTLS_CIPHER_AES_GCM_128_TAG_SIZE = 16 22 kTLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE = 8 23 24 kTLSOverhead = 16 25 ) 26 27 /* From linux/tls.h 28 struct tls_crypto_info { 29 unsigned short version; 30 unsigned short cipher_type; 31 }; 32 33 struct tls12_crypto_info_aes_gcm_128 { 34 struct tls_crypto_info info; 35 unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE]; 36 unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE]; 37 unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE]; 38 unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; 39 }; */ 40 41 type kTLSCryptoInfo struct { 42 version uint16 43 cipherType uint16 44 iv [kTLS_CIPHER_AES_GCM_128_IV_SIZE]byte 45 key [kTLS_CIPHER_AES_GCM_128_KEY_SIZE]byte 46 salt [kTLS_CIPHER_AES_GCM_128_SALT_SIZE]byte 47 recSeq [kTLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]byte 48 } 49 50 const kTLSCryptoInfoSize = 2 + 2 + kTLS_CIPHER_AES_GCM_128_IV_SIZE + kTLS_CIPHER_AES_GCM_128_KEY_SIZE + 51 kTLS_CIPHER_AES_GCM_128_SALT_SIZE + kTLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 52 53 // kTLSCipher is a placeholder to tell the record layer to skip wrapping. 54 type kTLSCipher struct{} 55 56 func kTLSEnable(c *net.TCPConn, key, iv, seq []byte) error { 57 if len(key) != kTLS_CIPHER_AES_GCM_128_KEY_SIZE { 58 panic("kTLS: wrong key length") 59 } 60 if len(iv) != kTLS_CIPHER_AES_GCM_128_SALT_SIZE { 61 panic("kTLS: wrong iv length") 62 } 63 if len(seq) != kTLS_CIPHER_AES_GCM_128_IV_SIZE { 64 panic("kTLS: wrong seq length") 65 } 66 67 cryptoInfo := kTLSCryptoInfo{ 68 version: VersionTLS12, 69 cipherType: kTLS_CIPHER_AES_GCM_128, 70 } 71 copy(cryptoInfo.salt[:], iv) 72 copy(cryptoInfo.key[:], key) 73 copy(cryptoInfo.iv[:], seq) 74 copy(cryptoInfo.recSeq[:], seq) 75 76 // Assert padding isn't introduced by alignment requirements. 77 if unsafe.Sizeof(cryptoInfo) != kTLSCryptoInfoSize { 78 panic("kTLS: wrong cryptoInfo size") 79 } 80 81 rwc, err := c.SyscallConn() 82 if err != nil { 83 return err 84 } 85 return rwc.Control(func(fd uintptr) { 86 err := syscall.SetsockoptString(int(fd), syscall.SOL_TCP, TCP_ULP, "tls") 87 if err != nil { 88 log.Println("kTLS: setsockopt(SOL_TCP, TCP_ULP) failed:", err) 89 } 90 err = syscall.SetsockoptString(int(fd), SOL_TLS, TLS_TX, 91 string((*[kTLSCryptoInfoSize]byte)(unsafe.Pointer(&cryptoInfo))[:])) 92 if err != nil { 93 log.Println("kTLS: setsockopt(SOL_TLS, TLS_TX) failed:", err) 94 } 95 }) 96 }