210 lines
5.5 KiB
Go
210 lines
5.5 KiB
Go
/*
|
|
** Copyright (c) 2017 Arnaud Ysmal. 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.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
|
|
*/
|
|
|
|
package cryptodev
|
|
|
|
import (
|
|
"os"
|
|
"runtime"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
fd *os.File
|
|
sfd int = -1
|
|
)
|
|
|
|
const (
|
|
COP_ENCRYPT = 1
|
|
COP_DECRYPT = 2
|
|
COP_F_BATCH = 0x0008 /* Batch op if possible */
|
|
|
|
CRYPTO_DES_CBC = 1
|
|
CRYPTO_3DES_CBC = 2
|
|
CRYPTO_BLF_CBC = 3
|
|
CRYPTO_CAST_CBC = 4
|
|
CRYPTO_SKIPJACK_CBC = 5
|
|
CRYPTO_MD5_HMAC = 6
|
|
CRYPTO_SHA1_HMAC = 7
|
|
CRYPTO_RIPEMD160_HMAC = 8
|
|
CRYPTO_MD5_KPDK = 9
|
|
CRYPTO_SHA1_KPDK = 10
|
|
CRYPTO_RIJNDAEL128_CBC = 11 /* 128 bit blocksize */
|
|
CRYPTO_AES_CBC = 11 /* 128 bit blocksize -- the same as above */
|
|
CRYPTO_ARC4 = 12
|
|
CRYPTO_MD5 = 13
|
|
CRYPTO_SHA1 = 14
|
|
CRYPTO_NULL_HMAC = 15
|
|
CRYPTO_NULL_CBC = 16
|
|
CRYPTO_DEFLATE_COMP = 17 /* Deflate compression algorithm */
|
|
CRYPTO_SHA2_256_HMAC = 18
|
|
CRYPTO_SHA2_384_HMAC = 19
|
|
CRYPTO_SHA2_512_HMAC = 20
|
|
CRYPTO_CAMELLIA_CBC = 21
|
|
CRYPTO_AES_XTS = 22
|
|
CRYPTO_AES_ICM = 23 /* commonly known as CTR mode */
|
|
CRYPTO_AES_NIST_GMAC = 24 /* cipher side */
|
|
CRYPTO_AES_NIST_GCM_16 = 25 /* 16 byte ICV */
|
|
CRYPTO_AES_128_NIST_GMAC = 26 /* auth side */
|
|
CRYPTO_AES_192_NIST_GMAC = 27 /* auth side */
|
|
CRYPTO_AES_256_NIST_GMAC = 28 /* auth side */
|
|
|
|
CRIOGET = uint32(0xc0046364)
|
|
CRIOASYMFEAT = uint32(0x40046369)
|
|
CRIOFINDDEV = uint32(0xc024636c)
|
|
CIOCGSESSION = uint32(0xc01c6365)
|
|
CIOCFSESSION = uint32(0x80046366)
|
|
CIOCCRYPT = uint32(0xc01c6367)
|
|
CIOCKEY = uint32(0xc0506368)
|
|
CIOCASYMFEAT = uint32(0x40046369)
|
|
CIOCGSESSION2 = uint32(0xc030636a)
|
|
CIOCKEY2 = uint32(0xc050636b)
|
|
CIOCFINDDEV = uint32(0xc024636c)
|
|
CIOCCRYPTAEAD = uint32(0xc028636d)
|
|
)
|
|
|
|
type session_op struct {
|
|
cipher uint32
|
|
mac uint32
|
|
keylen uint32
|
|
key uintptr
|
|
mackeylen int
|
|
mackey uintptr
|
|
ses uint32
|
|
}
|
|
|
|
type session2_op struct {
|
|
cipher uint32
|
|
mac uint32
|
|
keylen uint32
|
|
key uintptr
|
|
mackeylen int
|
|
mackey uintptr
|
|
ses uint32
|
|
crid int
|
|
pad [4]int
|
|
}
|
|
|
|
type crypt_op struct {
|
|
ses uint32
|
|
op uint16
|
|
flags uint16
|
|
len uint
|
|
src uintptr
|
|
dst uintptr
|
|
mac uintptr
|
|
iv uintptr
|
|
}
|
|
|
|
type Session struct {
|
|
s uint32
|
|
}
|
|
|
|
func init() {
|
|
var err error
|
|
var errno syscall.Errno
|
|
|
|
fd, err = os.OpenFile("/dev/crypto", os.O_RDWR, 0)
|
|
if err != nil {
|
|
return
|
|
}
|
|
_, _, errno = syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(fd.Fd()), uintptr(CRIOGET), uintptr(unsafe.Pointer(&sfd)))
|
|
if errno != 0 {
|
|
fini()
|
|
return
|
|
}
|
|
_, _, errno = syscall.RawSyscall(syscall.SYS_FCNTL, uintptr(sfd), syscall.F_SETFD, uintptr(1))
|
|
if errno != 0 {
|
|
fini()
|
|
}
|
|
}
|
|
|
|
func fini() {
|
|
if sfd != -1 {
|
|
syscall.Close(sfd)
|
|
sfd = -1
|
|
}
|
|
if fd != nil {
|
|
fd.Close()
|
|
fd = nil
|
|
}
|
|
}
|
|
|
|
func closeSession(s *Session) {
|
|
syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(sfd), uintptr(CIOCFSESSION), uintptr(unsafe.Pointer(&s)))
|
|
}
|
|
|
|
func NewSession(cipher uint32, key []byte) (*Session, error) {
|
|
var cs session_op
|
|
|
|
cs.cipher = cipher
|
|
cs.keylen = uint32(len(key))
|
|
cs.key = uintptr(unsafe.Pointer(&key[0]))
|
|
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(sfd), uintptr(CIOCGSESSION), uintptr(unsafe.Pointer(&cs)))
|
|
if errno != 0 {
|
|
return nil, errno
|
|
}
|
|
s := &Session{cs.ses}
|
|
runtime.SetFinalizer(s, closeSession)
|
|
return s, nil
|
|
}
|
|
|
|
func (s Session) Encrypt(dst []byte, src []byte, iv []byte) error {
|
|
var co crypt_op
|
|
var errno syscall.Errno
|
|
|
|
co.ses = s.s
|
|
co.op = COP_ENCRYPT
|
|
co.len = uint(len(src))
|
|
co.src = uintptr(unsafe.Pointer(&src[0]))
|
|
co.dst = uintptr(unsafe.Pointer(&dst[0]))
|
|
co.iv = uintptr(unsafe.Pointer(&iv[0]))
|
|
|
|
_, _, errno = syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(sfd), uintptr(CIOCCRYPT), uintptr(unsafe.Pointer(&co)))
|
|
if errno != 0 {
|
|
return errno
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s Session) Decrypt(dst []byte, src []byte, iv []byte) error {
|
|
var co crypt_op
|
|
var errno syscall.Errno
|
|
|
|
co.ses = s.s
|
|
co.op = COP_DECRYPT
|
|
co.len = uint(len(src))
|
|
co.src = uintptr(unsafe.Pointer(&src[0]))
|
|
co.dst = uintptr(unsafe.Pointer(&dst[0]))
|
|
co.iv = uintptr(unsafe.Pointer(&iv[0]))
|
|
|
|
_, _, errno = syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(sfd), uintptr(CIOCCRYPT), uintptr(unsafe.Pointer(&co)))
|
|
if errno != 0 {
|
|
return errno
|
|
}
|
|
return nil
|
|
}
|