Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: keystore.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)keystore.fth 1.3 06/11/22 | |
43 | purpose: | |
44 | copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | headerless | |
48 | ||
49 | 0 value keystore-ihandle | |
50 | 0 value keystore-buf \ Cached data | |
51 | 0 value /keystore \ Size of keystore partition | |
52 | ||
53 | alias keystore-ready? keystore-ihandle | |
54 | ||
55 | struct | |
56 | /w field >keystore-magic | |
57 | /w field >keystore-len \ Keystore data length, including header | |
58 | /w field >keystore-crc | |
59 | constant /keystore-header | |
60 | ||
61 | : keystore-len@ ( -- n ) keystore-buf >keystore-len w@ ; | |
62 | : keystore-len! ( n -- ) keystore-buf >keystore-len w! ; | |
63 | ||
64 | : keydata-start@ ( -- adr ) keystore-buf /keystore-header + ; | |
65 | : keydata-end@ ( -- adr ) keystore-buf keystore-len@ + ; | |
66 | ||
67 | : keyrecord-len@ ( adr -- n ) dup count ca+ count ca+ swap - ; | |
68 | ||
69 | : keystore-open ( -- ihandle | 0 ) | |
70 | d# 256 dup alloc-mem swap over >r ( va len ) ( r: va ) | |
71 | 0 r@ c! ( va len ) | |
72 | nvram-package phandle>devname r@ $cat ( va len ) | |
73 | " :keys" r@ $cat ( va len ) | |
74 | r> count open-dev ( va len ihandle ) ( r: ) | |
75 | -rot free-mem ( ihandle ) | |
76 | ; | |
77 | ||
78 | : $call-keystore-method ( ?? method$ -- ?? ) keystore-ihandle $call-method ; | |
79 | ||
80 | : keystore-seek ( offset -- ) 0 " seek" $call-keystore-method throw ; | |
81 | ||
82 | : keystore-read ( adr len -- ) | |
83 | keystore-ihandle 0= if 2drop exit then | |
84 | tuck " read" $call-keystore-method <> throw | |
85 | ; | |
86 | ||
87 | : keystore-write ( adr len -- ) | |
88 | keystore-ihandle 0= if 2drop exit then | |
89 | tuck " write" $call-keystore-method <> throw | |
90 | ; | |
91 | ||
92 | : (keystore-crc) ( accumulator adr len -- n ) | |
93 | bounds ?do i c@ + wbsplit + loop | |
94 | ; | |
95 | ||
96 | : keystore-crc ( -- crc ) | |
97 | keystore-buf keystore-len@ ( adr len ) | |
98 | 2dup wbsplit + swap /w 2* (keystore-crc) -rot ( n adr len ) | |
99 | /keystore-header tuck - >r + r> (keystore-crc) ( crc ) | |
100 | ; | |
101 | ||
102 | : keystore-sync ( -- ) | |
103 | 0 keystore-seek ( ) | |
104 | keystore-crc keystore-buf tuck >keystore-crc w! ( adr ) | |
105 | dup >keystore-len w@ keystore-write ( ) | |
106 | ; | |
107 | ||
108 | : keystore-init ( -- ) | |
109 | keystore-buf dup /keystore erase ( adr ) | |
110 | h# cd63 over >keystore-magic w! ( adr ) | |
111 | /keystore-header swap >keystore-len w! ( ) | |
112 | keystore-sync ( ) | |
113 | ; | |
114 | ||
115 | : init-keystore-partition ( -- ) | |
116 | keystore-ihandle if exit then ( ) | |
117 | ||
118 | keystore-open dup is keystore-ihandle 0= if ( ) | |
119 | cmn-error[ " Could not open security keystore device" ]cmn-end | |
120 | -1 throw | |
121 | then ( ) | |
122 | ||
123 | " size" $call-keystore-method dup is /keystore ( size ) | |
124 | dup alloc-mem tuck swap erase is keystore-buf ( ) | |
125 | ||
126 | 0 keystore-seek ( ) | |
127 | keystore-buf /keystore-header keystore-read ( ) | |
128 | keystore-buf >keystore-magic w@ h# cd63 <> if ( ) | |
129 | cmn-note[ " Initializing security keystore" ]cmn-end | |
130 | keystore-init exit ( ) | |
131 | then ( ) | |
132 | ||
133 | keydata-start@ keydata-end@ over - ( adr len ) | |
134 | ['] keystore-read catch 0= if ( ) | |
135 | keystore-buf >keystore-crc w@ keystore-crc = if ( ) | |
136 | exit ( ) | |
137 | then ( ) | |
138 | else ( adr len ) | |
139 | 2drop ( ) | |
140 | then ( ) | |
141 | cmn-error[ | |
142 | " Security keystore contents corrupt; Reinitializing keystore" | |
143 | ]cmn-end | |
144 | keystore-init ( ) | |
145 | ; | |
146 | ||
147 | \ Locate the named key in keystore. | |
148 | : find-security-key ( key$ -- adr | 0 ) | |
149 | 2>r ( ) ( r: key$ ) | |
150 | keydata-end@ keydata-start@ ( end start ) | |
151 | begin 2dup > while ( end nxt ) | |
152 | dup count 2dup 2r@ $= if ( end nxt $ ) | |
153 | 2drop nip 2r> 2drop exit ( nxt ) ( r: ) | |
154 | else ( end nxt $ ) | |
155 | rot drop ca+ count ca+ ( end nxt' ) | |
156 | then ( end nxt' ) | |
157 | repeat 2drop ( ) | |
158 | 2r> 2drop 0 ( 0 ) ( r: ) | |
159 | ; | |
160 | ||
161 | \ Add a key record entry. | |
162 | : add-keyrecord-entry ( name,len data,len -- ) | |
163 | keydata-end@ >r ( name,len data,len ) ( r: adr ) | |
164 | 2swap r@ pack count ca+ pack count ca+ ( adr' ) | |
165 | r> - keystore-len@ + keystore-len! ( ) ( r: ) | |
166 | ; | |
167 | ||
168 | \ Delete a keyrecord entry | |
169 | : delete-keyrecord-entry ( adr -- ) | |
170 | dup keyrecord-len@ dup >r ( adr n ) ( r: n ) | |
171 | over ca+ keydata-end@ over - rot swap move ( ) | |
172 | keystore-len@ r> - keystore-len! ( ) ( r: ) | |
173 | ; | |
174 | ||
175 | \ Check keystore space availability. | |
176 | : enough-key-room? ( name,len keydata,len -- flag ) | |
177 | nip over + 2+ >r ( name,len ) ( r: total ) | |
178 | /keystore keystore-len@ - ( name,len nfree ) | |
179 | -rot find-security-key ?dup if ( nfree keyrecord-adr ) | |
180 | count tuck ca+ count nip + 2+ + ( avail ) | |
181 | then ( avail ) | |
182 | r> >= ( flag ) ( r: ) | |
183 | ; | |
184 | ||
185 | d# 64 constant max-keyname-len \ Keyname can be upto 64 characters | |
186 | d# 32 constant max-keydata-len \ Keydata can be upto 32 bytes | |
187 | ||
188 | \ Key retrieval. Returns length of the key on success, or one of the | |
189 | \ following codes on failure: | |
190 | \ -1 Invalid argument (Key name too long) | |
191 | \ -2 Buffer too small to hold key data | |
192 | \ -3 Key does not exist | |
193 | \ -4 Could not access keystore | |
194 | ||
195 | : (get-security-key) ( key$ -- keydata,len ) | |
196 | find-security-key ?dup if count ca+ count else 0 0 then | |
197 | ; | |
198 | ||
199 | cif: SUNW,get-security-key ( len buf cname -- keylen | error# ) | |
200 | >r swap r> cscount ( buf len keyname$ ) | |
201 | dup max-keyname-len > if ( buf len keyname$ ) | |
202 | 2drop 2drop -1 exit | |
203 | then ( buf len keyname$ ) | |
204 | keystore-ready? 0= if ( buf len keyname$ ) | |
205 | 2drop 2drop -4 exit | |
206 | then ( buf len keyname$ ) | |
207 | (get-security-key) dup 0= if ( buf len keydata keylen ) | |
208 | 2drop 2drop -3 exit | |
209 | then ( buf len keydata keylen ) | |
210 | rot over < if ( buf keydata keylen ) | |
211 | 3drop -2 exit | |
212 | then ( buf keydata keylen ) | |
213 | dup >r rot swap move r> ( keylen ) | |
214 | ; | |
215 | ||
216 | [ifdef] SUN4V | |
217 | : init-ldoms-keystore-partition ( -- ) | |
218 | h# 100 dup is /keystore ( size ) | |
219 | dup alloc-mem tuck swap erase dup is keystore-buf ( adr ) | |
220 | h# cd63 over >keystore-magic w! ( adr ) | |
221 | /keystore-header swap >keystore-len w! ( ) | |
222 | true to keystore-ready? | |
223 | ; | |
224 | ||
225 | d# 64 buffer: hexascii-buf | |
226 | ||
227 | \ Get ASCII hexadecimal representation of octet stream | |
228 | : key>ascii ( data datalen -- buf buflen ) | |
229 | hexascii-buf 0 2swap ( buf 0 data datalen ) | |
230 | dup 0= over d# 32 > or if ( buf 0 data datalen ) | |
231 | 2drop exit ( buf 0 ) | |
232 | then ( buf 0 data datalen ) | |
233 | base @ >r hex ( buf 0 data datalen ) | |
234 | bounds ?do ( buf len ) | |
235 | i c@ <# u# u# u#> ( buf len $ ) | |
236 | 2over ca+ swap move ( buf len ) | |
237 | 2+ ( buf len' ) | |
238 | loop ( buf len' ) | |
239 | 2dup upper ( buf len' ) | |
240 | r> base ! ( buf buflen ) | |
241 | ; | |
242 | ||
243 | \ These words are called if the keystore domain-service has not yet | |
244 | \ been attached (when first loading the keystore MD node) | |
245 | : no-ds-set ( data,len name,len -- ) 2drop 2drop ; | |
246 | : no-ds-unset ( name,len -- ) 2drop ; | |
247 | ||
248 | defer key-set ['] no-ds-set is key-set | |
249 | defer key-delete ['] no-ds-unset is key-delete | |
250 | ||
251 | \ #### sync is needed so we can switch back and forth between | |
252 | \ #### domain service and svc-channel. It will be removed | |
253 | defer key-sync ['] noop is key-sync | |
254 | ||
255 | \ Store security key in keystore. | |
256 | : write-security-key ( name,len data,len -- keylen ) | |
257 | 2over find-security-key ?dup if ( name,len data,len adr ) | |
258 | delete-keyrecord-entry ( name,len data,len ) | |
259 | then ( name,len data,len ) | |
260 | dup if ( name,len data,len ) | |
261 | 2over 2over key>ascii 2swap key-set ( name,len data,len ) | |
262 | dup >r add-keyrecord-entry r> ( keylen ) | |
263 | else ( name,len data,len ) | |
264 | 2drop key-delete 0 ( 0 ) | |
265 | then ( keylen ) | |
266 | key-sync | |
267 | ; | |
268 | [else] | |
269 | \ Store security key in keystore. | |
270 | : write-security-key ( name,len data,len -- keylen ) | |
271 | 2over find-security-key ?dup if ( name,len data,len adr ) | |
272 | delete-keyrecord-entry ( name,len data,len ) | |
273 | then ( name,len data,len ) | |
274 | dup if ( name,len data,len ) | |
275 | dup >r add-keyrecord-entry r> ( keylen ) | |
276 | else ( name,len data,len ) | |
277 | 2drop 2drop 0 ( 0 ) | |
278 | then ( keylen ) | |
279 | keystore-sync ( keylen ) | |
280 | ; | |
281 | [then] | |
282 | ||
283 | ||
284 | \ Key storage/deletion. A key length of zero is used to delete the | |
285 | \ named key. On success, the length of stored key is returned; a return | |
286 | \ value of zero indicates successful key deletion. Possible error | |
287 | \ return values are | |
288 | \ -1 Invalid arguments (Key name or value too long) | |
289 | \ -2 Key to delete does not exist | |
290 | \ -3 Out of key storage space | |
291 | \ -4 Could not access keystore | |
292 | ||
293 | : (set-security-key) ( name,len data,len -- len' | error# ) | |
294 | 2 pick max-keyname-len > over max-keydata-len > or if | |
295 | 2drop 2drop -1 exit | |
296 | then ( name,len data,len ) | |
297 | keystore-ready? 0= if | |
298 | 2drop 2drop -4 exit | |
299 | then ( name,len data,len ) | |
300 | dup 0= if | |
301 | 2over find-security-key 0= if | |
302 | 2drop 2drop -2 exit | |
303 | then | |
304 | then ( name,len data,len ) | |
305 | 2over 2over enough-key-room? 0= if | |
306 | 2drop 2drop -3 exit | |
307 | then ( name,len data,len ) | |
308 | write-security-key | |
309 | ; | |
310 | ||
311 | cif: SUNW,set-security-key ( len buf cname -- len' | error# ) | |
312 | >r swap r> cscount 2swap (set-security-key) | |
313 | ; | |
314 | ||
315 | max-keydata-len buffer: keydata-buf \ Buffer to hold raw keydata | |
316 | ||
317 | : convert-key ( keyvalue$ -- [ keydata datalen ] valid? ) | |
318 | dup 2 mod 0<> over 2/ max-keydata-len > or if ( keyvalue$ ) | |
319 | 2drop false exit ( false ) | |
320 | then ( keyvalue$ ) | |
321 | keydata-buf 0 2swap bounds ?do ( keydata,len ) | |
322 | i 2 $hnumber if ( keydata,len ) | |
323 | 2drop false unloop exit ( false ) | |
324 | then ( keydata,len n ) | |
325 | >r 2dup ca+ r> swap c! ( keydata,len ) | |
326 | 1+ ( keydata,len' ) | |
327 | 2 +loop true ( keydata,len' true ) | |
328 | ; | |
329 | ||
330 | headers | |
331 | also forth definitions | |
332 | ||
333 | \ Command line interface to store/delete security keys. | |
334 | : set-security-key \ keyname keyvalue ( -- ) | |
335 | safe-parse-word parse-word dup if ( name$ value$ ) | |
336 | 2dup convert-key 0= if ( name$ value$ ) | |
337 | ." Invalid keyvalue '" type ." '" cr | |
338 | 2drop exit ( ) | |
339 | else ( name$ value$ keydata,len ) | |
340 | 2swap 2drop ( name$ keydata,len ) | |
341 | then ( name$ keydata,len ) | |
342 | then ( name$ keydata,len ) | |
343 | 2over 2over (set-security-key) ( name$ keydata,len result ) | |
344 | dup 0< if ( name$ keydata,len error# ) | |
345 | case | |
346 | -1 of ." Key name or value too long" endof | |
347 | -2 of ." Key to delete does not exist" endof | |
348 | -3 of ." Out of key storage space" endof | |
349 | -4 of ." Could not update key data" endof | |
350 | endcase ( name$ keydata,len ) | |
351 | 2drop 2drop ( ) | |
352 | else ( name$ keydata,len len' ) | |
353 | drop nip 0= if ( name$ ) | |
354 | ." Key '" 2dup type ." ' deleted" cr ( name$ ) | |
355 | then 2drop ( ) | |
356 | then ( ) | |
357 | ; | |
358 | ||
359 | \ List names of keys stored in the keystore. Key values are not printed. | |
360 | : list-security-keys ( -- ) | |
361 | keydata-end@ keydata-start@ ( end start ) | |
362 | begin 2dup > while ( end nxt ) | |
363 | dup count type cr dup keyrecord-len@ ca+ ( end nxt' ) | |
364 | repeat 2drop ( ) | |
365 | ; | |
366 | ||
367 | previous | |
368 | ||
369 | stand-init: initialize security key structure | |
370 | [ifdef] SUN4V | |
371 | init-ldoms-keystore-partition | |
372 | [else] | |
373 | init-keystore-partition | |
374 | [then] | |
375 | ; |