github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/boring/aes.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan 6 7 package boring 8 9 /* 10 11 #include "goboringcrypto.h" 12 13 // These wrappers allocate out_len on the C stack, and check that it matches the expected 14 // value, to avoid having to pass a pointer from Go, which would escape to the heap. 15 16 int EVP_AEAD_CTX_seal_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out, 17 size_t exp_out_len, 18 const uint8_t *nonce, size_t nonce_len, 19 const uint8_t *in, size_t in_len, 20 const uint8_t *ad, size_t ad_len) { 21 size_t out_len; 22 int ok = _goboringcrypto_EVP_AEAD_CTX_seal(ctx, out, &out_len, exp_out_len, 23 nonce, nonce_len, in, in_len, ad, ad_len); 24 if (out_len != exp_out_len) { 25 return 0; 26 } 27 return ok; 28 }; 29 30 int EVP_AEAD_CTX_open_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out, 31 size_t exp_out_len, 32 const uint8_t *nonce, size_t nonce_len, 33 const uint8_t *in, size_t in_len, 34 const uint8_t *ad, size_t ad_len) { 35 size_t out_len; 36 int ok = _goboringcrypto_EVP_AEAD_CTX_open(ctx, out, &out_len, exp_out_len, 37 nonce, nonce_len, in, in_len, ad, ad_len); 38 if (out_len != exp_out_len) { 39 return 0; 40 } 41 return ok; 42 }; 43 44 */ 45 import "C" 46 import ( 47 "bytes" 48 "crypto/cipher" 49 "errors" 50 "runtime" 51 "strconv" 52 "unsafe" 53 ) 54 55 type aesKeySizeError int 56 57 func (k aesKeySizeError) Error() string { 58 return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) 59 } 60 61 const aesBlockSize = 16 62 63 type aesCipher struct { 64 key []byte 65 enc C.GO_AES_KEY 66 dec C.GO_AES_KEY 67 } 68 69 type extraModes interface { 70 // Copied out of crypto/aes/modes.go. 71 NewCBCEncrypter(iv []byte) cipher.BlockMode 72 NewCBCDecrypter(iv []byte) cipher.BlockMode 73 NewCTR(iv []byte) cipher.Stream 74 NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) 75 } 76 77 var _ extraModes = (*aesCipher)(nil) 78 79 func NewAESCipher(key []byte) (cipher.Block, error) { 80 c := &aesCipher{key: bytes.Clone(key)} 81 // Note: 0 is success, contradicting the usual BoringCrypto convention. 82 if C._goboringcrypto_AES_set_decrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.dec) != 0 || 83 C._goboringcrypto_AES_set_encrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.enc) != 0 { 84 return nil, aesKeySizeError(len(key)) 85 } 86 return c, nil 87 } 88 89 func (c *aesCipher) BlockSize() int { return aesBlockSize } 90 91 func (c *aesCipher) Encrypt(dst, src []byte) { 92 if inexactOverlap(dst, src) { 93 panic("crypto/cipher: invalid buffer overlap") 94 } 95 if len(src) < aesBlockSize { 96 panic("crypto/aes: input not full block") 97 } 98 if len(dst) < aesBlockSize { 99 panic("crypto/aes: output not full block") 100 } 101 C._goboringcrypto_AES_encrypt( 102 (*C.uint8_t)(unsafe.Pointer(&src[0])), 103 (*C.uint8_t)(unsafe.Pointer(&dst[0])), 104 &c.enc) 105 } 106 107 func (c *aesCipher) Decrypt(dst, src []byte) { 108 if inexactOverlap(dst, src) { 109 panic("crypto/cipher: invalid buffer overlap") 110 } 111 if len(src) < aesBlockSize { 112 panic("crypto/aes: input not full block") 113 } 114 if len(dst) < aesBlockSize { 115 panic("crypto/aes: output not full block") 116 } 117 C._goboringcrypto_AES_decrypt( 118 (*C.uint8_t)(unsafe.Pointer(&src[0])), 119 (*C.uint8_t)(unsafe.Pointer(&dst[0])), 120 &c.dec) 121 } 122 123 type aesCBC struct { 124 key *C.GO_AES_KEY 125 mode C.int 126 iv [aesBlockSize]byte 127 } 128 129 func (x *aesCBC) BlockSize() int { return aesBlockSize } 130 131 func (x *aesCBC) CryptBlocks(dst, src []byte) { 132 if inexactOverlap(dst, src) { 133 panic("crypto/cipher: invalid buffer overlap") 134 } 135 if len(src)%aesBlockSize != 0 { 136 panic("crypto/cipher: input not full blocks") 137 } 138 if len(dst) < len(src) { 139 panic("crypto/cipher: output smaller than input") 140 } 141 if len(src) > 0 { 142 C._goboringcrypto_AES_cbc_encrypt( 143 (*C.uint8_t)(unsafe.Pointer(&src[0])), 144 (*C.uint8_t)(unsafe.Pointer(&dst[0])), 145 C.size_t(len(src)), x.key, 146 (*C.uint8_t)(unsafe.Pointer(&x.iv[0])), x.mode) 147 } 148 } 149 150 func (x *aesCBC) SetIV(iv []byte) { 151 if len(iv) != aesBlockSize { 152 panic("cipher: incorrect length IV") 153 } 154 copy(x.iv[:], iv) 155 } 156 157 func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode { 158 x := &aesCBC{key: &c.enc, mode: C.GO_AES_ENCRYPT} 159 copy(x.iv[:], iv) 160 return x 161 } 162 163 func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { 164 x := &aesCBC{key: &c.dec, mode: C.GO_AES_DECRYPT} 165 copy(x.iv[:], iv) 166 return x 167 } 168 169 type aesCTR struct { 170 key *C.GO_AES_KEY 171 iv [aesBlockSize]byte 172 num C.uint 173 ecount_buf [16]C.uint8_t 174 } 175 176 func (x *aesCTR) XORKeyStream(dst, src []byte) { 177 if inexactOverlap(dst, src) { 178 panic("crypto/cipher: invalid buffer overlap") 179 } 180 if len(dst) < len(src) { 181 panic("crypto/cipher: output smaller than input") 182 } 183 if len(src) == 0 { 184 return 185 } 186 C._goboringcrypto_AES_ctr128_encrypt( 187 (*C.uint8_t)(unsafe.Pointer(&src[0])), 188 (*C.uint8_t)(unsafe.Pointer(&dst[0])), 189 C.size_t(len(src)), x.key, (*C.uint8_t)(unsafe.Pointer(&x.iv[0])), 190 &x.ecount_buf[0], &x.num) 191 } 192 193 func (c *aesCipher) NewCTR(iv []byte) cipher.Stream { 194 x := &aesCTR{key: &c.enc} 195 copy(x.iv[:], iv) 196 return x 197 } 198 199 type aesGCM struct { 200 ctx C.GO_EVP_AEAD_CTX 201 aead *C.GO_EVP_AEAD 202 } 203 204 const ( 205 gcmBlockSize = 16 206 gcmTagSize = 16 207 gcmStandardNonceSize = 12 208 ) 209 210 type aesNonceSizeError int 211 212 func (n aesNonceSizeError) Error() string { 213 return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n)) 214 } 215 216 type noGCM struct { 217 cipher.Block 218 } 219 220 func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { 221 if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize { 222 return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time") 223 } 224 // Fall back to standard library for GCM with non-standard nonce or tag size. 225 if nonceSize != gcmStandardNonceSize { 226 return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize) 227 } 228 if tagSize != gcmTagSize { 229 return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) 230 } 231 return c.newGCM(false) 232 } 233 234 func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { 235 return c.(*aesCipher).newGCM(true) 236 } 237 238 func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) { 239 var aead *C.GO_EVP_AEAD 240 switch len(c.key) * 8 { 241 case 128: 242 if tls { 243 aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12() 244 } else { 245 aead = C._goboringcrypto_EVP_aead_aes_128_gcm() 246 } 247 case 256: 248 if tls { 249 aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12() 250 } else { 251 aead = C._goboringcrypto_EVP_aead_aes_256_gcm() 252 } 253 default: 254 // Fall back to standard library for GCM with non-standard key size. 255 return cipher.NewGCMWithNonceSize(&noGCM{c}, gcmStandardNonceSize) 256 } 257 258 g := &aesGCM{aead: aead} 259 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 { 260 return nil, fail("EVP_AEAD_CTX_init") 261 } 262 // Note: Because of the finalizer, any time g.ctx is passed to cgo, 263 // that call must be followed by a call to runtime.KeepAlive(g), 264 // to make sure g is not collected (and finalized) before the cgo 265 // call returns. 266 runtime.SetFinalizer(g, (*aesGCM).finalize) 267 if g.NonceSize() != gcmStandardNonceSize { 268 panic("boringcrypto: internal confusion about nonce size") 269 } 270 if g.Overhead() != gcmTagSize { 271 panic("boringcrypto: internal confusion about tag size") 272 } 273 274 return g, nil 275 } 276 277 func (g *aesGCM) finalize() { 278 C._goboringcrypto_EVP_AEAD_CTX_cleanup(&g.ctx) 279 } 280 281 func (g *aesGCM) NonceSize() int { 282 return int(C._goboringcrypto_EVP_AEAD_nonce_length(g.aead)) 283 } 284 285 func (g *aesGCM) Overhead() int { 286 return int(C._goboringcrypto_EVP_AEAD_max_overhead(g.aead)) 287 } 288 289 // base returns the address of the underlying array in b, 290 // being careful not to panic when b has zero length. 291 func base(b []byte) *C.uint8_t { 292 if len(b) == 0 { 293 return nil 294 } 295 return (*C.uint8_t)(unsafe.Pointer(&b[0])) 296 } 297 298 func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { 299 if len(nonce) != gcmStandardNonceSize { 300 panic("cipher: incorrect nonce length given to GCM") 301 } 302 if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) { 303 panic("cipher: message too large for GCM") 304 } 305 if len(dst)+len(plaintext)+gcmTagSize < len(dst) { 306 panic("cipher: message too large for buffer") 307 } 308 309 // Make room in dst to append plaintext+overhead. 310 n := len(dst) 311 for cap(dst) < n+len(plaintext)+gcmTagSize { 312 dst = append(dst[:cap(dst)], 0) 313 } 314 dst = dst[:n+len(plaintext)+gcmTagSize] 315 316 // Check delayed until now to make sure len(dst) is accurate. 317 if inexactOverlap(dst[n:], plaintext) { 318 panic("cipher: invalid buffer overlap") 319 } 320 321 outLen := C.size_t(len(plaintext) + gcmTagSize) 322 ok := C.EVP_AEAD_CTX_seal_wrapper( 323 &g.ctx, 324 (*C.uint8_t)(unsafe.Pointer(&dst[n])), outLen, 325 base(nonce), C.size_t(len(nonce)), 326 base(plaintext), C.size_t(len(plaintext)), 327 base(additionalData), C.size_t(len(additionalData))) 328 runtime.KeepAlive(g) 329 if ok == 0 { 330 panic(fail("EVP_AEAD_CTX_seal")) 331 } 332 return dst[:n+int(outLen)] 333 } 334 335 var errOpen = errors.New("cipher: message authentication failed") 336 337 func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { 338 if len(nonce) != gcmStandardNonceSize { 339 panic("cipher: incorrect nonce length given to GCM") 340 } 341 if len(ciphertext) < gcmTagSize { 342 return nil, errOpen 343 } 344 if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize { 345 return nil, errOpen 346 } 347 348 // Make room in dst to append ciphertext without tag. 349 n := len(dst) 350 for cap(dst) < n+len(ciphertext)-gcmTagSize { 351 dst = append(dst[:cap(dst)], 0) 352 } 353 dst = dst[:n+len(ciphertext)-gcmTagSize] 354 355 // Check delayed until now to make sure len(dst) is accurate. 356 if inexactOverlap(dst[n:], ciphertext) { 357 panic("cipher: invalid buffer overlap") 358 } 359 360 outLen := C.size_t(len(ciphertext) - gcmTagSize) 361 ok := C.EVP_AEAD_CTX_open_wrapper( 362 &g.ctx, 363 base(dst[n:]), outLen, 364 base(nonce), C.size_t(len(nonce)), 365 base(ciphertext), C.size_t(len(ciphertext)), 366 base(additionalData), C.size_t(len(additionalData))) 367 runtime.KeepAlive(g) 368 if ok == 0 { 369 return nil, errOpen 370 } 371 return dst[:n+int(outLen)], nil 372 } 373 374 func anyOverlap(x, y []byte) bool { 375 return len(x) > 0 && len(y) > 0 && 376 uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && 377 uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) 378 } 379 380 func inexactOverlap(x, y []byte) bool { 381 if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { 382 return false 383 } 384 return anyOverlap(x, y) 385 }