cryptodev/cryptodev/cryptodev.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
}