-
Notifications
You must be signed in to change notification settings - Fork 11
/
caam_tool.go
199 lines (158 loc) · 4.54 KB
/
caam_tool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// NXP Cryptographic Acceleration and Assurance Module (CAAM)
// https://github.com/usbarmory/caam-keyblob
//
// userspace driver reference example
//
// Copyright (c) WithSecure Corporation
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation under version 3 of the License.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// See accompanying LICENSE file for full details.
//
// IMPORTANT: the unique OTPMK internal key is available only when Secure Boot
// (HAB) is enabled, otherwise a Non-volatile Test Key (NVTK), identical for
// each SoC, is used. The secure operation of the CAAM and SNVS, in production
// deployments, should always be paired with Secure Boot activation.
//
// +build linux
package main
import (
"bytes"
"flag"
"log"
"os"
"syscall"
"unsafe"
)
const CAAM_DEV = "/dev/caam_kb"
const (
KEYMOD_LEN = 16
BLOB_OVERHEAD = 32 + 16
MAX_KEYBLOB_LEN = 65535
MAX_RAWKEY_LEN = MAX_KEYBLOB_LEN - BLOB_OVERHEAD
)
// Portability note: the 0x18 within the two CAAM_KB_* constants and the uint32
// types in caam_kb_data reflect a 32-bit architecture.
const (
// _IOWR(CAAM_KB_MAGIC, 0, struct caam_kb_data)
CAAM_KB_ENCRYPT = 0xc0184900
// _IOWR(CAAM_KB_MAGIC, 1, struct caam_kb_data)
CAAM_KB_DECRYPT = 0xc0184901
)
// C compatible struct of caam_kb_data from caam_keyblob.h
type caam_kb_data struct {
Text *byte
TextLen uint32
Blob *byte
BlobLen uint32
Keymod *byte
KeymodLen uint32
}
func init() {
log.SetFlags(0)
log.SetOutput(os.Stdout)
flag.Usage = func() {
log.Println("usage: [enc|dec] [cleartext file] [blob file]")
}
}
func main() {
var err error
var mode uint32
var text []byte
var blob []byte
var output *os.File
flag.Parse()
if len(flag.Args()) != 3 {
flag.Usage()
os.Exit(1)
}
op := flag.Arg(0)
textPath := flag.Arg(1)
blobPath := flag.Arg(2)
switch op {
case "enc":
mode = CAAM_KB_ENCRYPT
case "dec":
mode = CAAM_KB_DECRYPT
default:
log.Fatal("caam_tool: error, invalid operation")
}
defer func() {
if err != nil {
log.Fatalf("caam_tool: error, %v", err)
}
}()
kb := &caam_kb_data{}
// The key modifier is left empty in this reference example, it is
// concatenated to the OTPMK to further differentiate derived keys.
keymod := bytes.Repeat([]byte{0x00}, KEYMOD_LEN)
kb.Keymod = &keymod[0]
kb.KeymodLen = KEYMOD_LEN
switch mode {
case CAAM_KB_ENCRYPT:
if text, err = os.ReadFile(textPath); err != nil {
return
}
if len(text) == 0 || len(text) > MAX_RAWKEY_LEN {
log.Fatal("caam_tool: error, invalid input size")
}
kb.TextLen = uint32(len(text))
kb.BlobLen = uint32(len(text) + BLOB_OVERHEAD)
blob = make([]byte, kb.BlobLen)
log.Printf("caam_tool: encrypting %d bytes from %s", kb.TextLen, textPath)
case CAAM_KB_DECRYPT:
if blob, err = os.ReadFile(blobPath); err != nil {
return
}
if len(blob) == 0 || len(blob) > MAX_KEYBLOB_LEN {
log.Fatal("caam_tool: error, invalid input size")
}
kb.BlobLen = uint32(len(blob))
kb.TextLen = uint32(len(blob) - BLOB_OVERHEAD)
text = make([]byte, kb.TextLen)
log.Printf("caam_tool: decrypting %d bytes from %s", kb.BlobLen, blobPath)
}
kb.Text = &text[0]
kb.Blob = &blob[0]
caam, err := os.OpenFile(CAAM_DEV, os.O_RDWR, 0600)
if err != nil {
return
}
syscall.Flock(int(caam.Fd()), syscall.LOCK_EX)
defer syscall.Flock(int(caam.Fd()), syscall.LOCK_UN)
defer caam.Close()
log.Printf("caam_tool: caam_kb_data %+v", kb)
log.Printf("caam_tool: issuing ioctl %x on %s", mode, CAAM_DEV)
if err = ioctl(caam.Fd(), uintptr(mode), uintptr(unsafe.Pointer(kb))); err != nil {
return
}
switch mode {
case CAAM_KB_ENCRYPT:
if output, err = os.OpenFile(blobPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL|os.O_SYNC, 0600); err != nil {
return
}
log.Printf("caam_tool: encrypted %d bytes to %s", kb.BlobLen, blobPath)
output.Write(blob)
case CAAM_KB_DECRYPT:
if output, err = os.OpenFile(textPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL|os.O_SYNC, 0600); err != nil {
return
}
log.Printf("caam_tool: decrypted %d bytes to %s", kb.TextLen, textPath)
output.Write(text)
}
output.Close()
}
func ioctl(fd, cmd, arg uintptr) (err error) {
_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, arg)
if e != 0 {
return syscall.Errno(e)
}
return
}