1 // Copyright 2018 Thales e-Security, Inc 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining 4 // a copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to 8 // permit persons to whom the Software is furnished to do so, subject to 9 // the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be 12 // included in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 package crypto11 23 24 import ( 25 "fmt" 26 27 "github.com/miekg/pkcs11" 28 ) 29 30 // cipher.Block --------------------------------------------------------- 31 32 // BlockSize returns the cipher's block size in bytes. 33 func (key *SecretKey) BlockSize() int { 34 return key.Cipher.BlockSize 35 } 36 37 // Decrypt decrypts the first block in src into dst. 38 // Dst and src must overlap entirely or not at all. 39 // 40 // Using this method for bulk operation is very inefficient, as it makes a round trip to the HSM 41 // (which may be network-connected) for each block. 42 // For more efficient operation, see NewCBCDecrypterCloser, NewCBCDecrypter or NewCBC. 43 func (key *SecretKey) Decrypt(dst, src []byte) { 44 var result []byte 45 if err := key.context.withSession(func(session *pkcs11Session) (err error) { 46 mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(key.Cipher.ECBMech, nil)} 47 if err = session.ctx.DecryptInit(session.handle, mech, key.handle); err != nil { 48 return 49 } 50 if result, err = session.ctx.Decrypt(session.handle, src[:key.Cipher.BlockSize]); err != nil { 51 return 52 } 53 if len(result) != key.Cipher.BlockSize { 54 err = fmt.Errorf("C_Decrypt: returned %v bytes, wanted %v", len(result), key.Cipher.BlockSize) 55 return 56 } 57 return 58 }); err != nil { 59 panic(err) 60 } else { 61 copy(dst[:key.Cipher.BlockSize], result) 62 } 63 } 64 65 // Encrypt encrypts the first block in src into dst. 66 // Dst and src must overlap entirely or not at all. 67 // 68 // Using this method for bulk operation is very inefficient, as it makes a round trip to the HSM 69 // (which may be network-connected) for each block. 70 // For more efficient operation, see NewCBCEncrypterCloser, NewCBCEncrypter or NewCBC. 71 func (key *SecretKey) Encrypt(dst, src []byte) { 72 var result []byte 73 if err := key.context.withSession(func(session *pkcs11Session) (err error) { 74 mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(key.Cipher.ECBMech, nil)} 75 if err = session.ctx.EncryptInit(session.handle, mech, key.handle); err != nil { 76 return 77 } 78 if result, err = session.ctx.Encrypt(session.handle, src[:key.Cipher.BlockSize]); err != nil { 79 return 80 } 81 if len(result) != key.Cipher.BlockSize { 82 err = fmt.Errorf("C_Encrypt: unexpectedly returned %v bytes, wanted %v", len(result), key.Cipher.BlockSize) 83 return 84 } 85 return 86 }); err != nil { 87 panic(err) 88 } else { 89 copy(dst[:key.Cipher.BlockSize], result) 90 } 91 } 92