1package s3crypto 2 3import ( 4 "io" 5) 6 7const ( 8 cbcKeySize = 32 9 cbcNonceSize = 16 10) 11 12type cbcContentCipherBuilder struct { 13 generator CipherDataGenerator 14 padder Padder 15} 16 17// AESCBCContentCipherBuilder returns a new encryption only AES/CBC mode structure using the provided padder. The provided cipher data generator 18// will be used to provide keys for content encryption. 19// 20// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 21func AESCBCContentCipherBuilder(generator CipherDataGenerator, padder Padder) ContentCipherBuilder { 22 return cbcContentCipherBuilder{generator: generator, padder: padder} 23} 24 25// RegisterAESCBCContentCipher registers the AES/CBC cipher and padder with the provided CryptoRegistry. 26// 27// Example: 28// cr := s3crypto.NewCryptoRegistry() 29// if err := s3crypto.RegisterAESCBCContentCipher(cr, s3crypto.AESCBCPadder); err != nil { 30// panic(err) // handle error 31// } 32// 33// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 34func RegisterAESCBCContentCipher(registry *CryptoRegistry, padder Padder) error { 35 if registry == nil { 36 return errNilCryptoRegistry 37 } 38 name := AESCBC + "/" + padder.Name() 39 err := registry.AddCEK(name, newAESCBCContentCipher) 40 if err != nil { 41 return err 42 } 43 if err := registry.AddPadder(name, padder); err != nil { 44 return err 45 } 46 return nil 47} 48 49func (builder cbcContentCipherBuilder) ContentCipher() (ContentCipher, error) { 50 cd, err := builder.generator.GenerateCipherData(cbcKeySize, cbcNonceSize) 51 if err != nil { 52 return nil, err 53 } 54 55 cd.Padder = builder.padder 56 return newAESCBCContentCipher(cd) 57} 58 59func (builder cbcContentCipherBuilder) isAWSFixture() bool { 60 return true 61} 62 63func (cbcContentCipherBuilder) isEncryptionVersionCompatible(version clientVersion) error { 64 if version != v1ClientVersion { 65 return errDeprecatedIncompatibleCipherBuilder 66 } 67 return nil 68} 69 70// newAESCBCContentCipher will create a new aes cbc content cipher. If the cipher data's 71// will set the cek algorithm if it hasn't been set. 72func newAESCBCContentCipher(cd CipherData) (ContentCipher, error) { 73 if len(cd.CEKAlgorithm) == 0 { 74 cd.CEKAlgorithm = AESCBC + "/" + cd.Padder.Name() 75 } 76 cipher, err := newAESCBC(cd, cd.Padder) 77 if err != nil { 78 return nil, err 79 } 80 81 return &aesCBCContentCipher{ 82 CipherData: cd, 83 Cipher: cipher, 84 }, nil 85} 86 87// aesCBCContentCipher will use AES CBC for the main cipher. 88type aesCBCContentCipher struct { 89 CipherData CipherData 90 Cipher Cipher 91} 92 93// EncryptContents will generate a random key and iv and encrypt the data using cbc 94func (cc *aesCBCContentCipher) EncryptContents(src io.Reader) (io.Reader, error) { 95 return cc.Cipher.Encrypt(src), nil 96} 97 98// DecryptContents will use the symmetric key provider to instantiate a new CBC cipher. 99// We grab a decrypt reader from CBC and wrap it in a CryptoReadCloser. The only error 100// expected here is when the key or iv is of invalid length. 101func (cc *aesCBCContentCipher) DecryptContents(src io.ReadCloser) (io.ReadCloser, error) { 102 reader := cc.Cipher.Decrypt(src) 103 return &CryptoReadCloser{Body: src, Decrypter: reader}, nil 104} 105 106// GetCipherData returns cipher data 107func (cc aesCBCContentCipher) GetCipherData() CipherData { 108 return cc.CipherData 109} 110 111var ( 112 _ ContentCipherBuilder = (*cbcContentCipherBuilder)(nil) 113 _ compatibleEncryptionFixture = (*cbcContentCipherBuilder)(nil) 114 _ awsFixture = (*cbcContentCipherBuilder)(nil) 115 116 _ ContentCipher = (*aesCBCContentCipher)(nil) 117) 118