= secstore: fetch data from Plan 9's secure storage service include "dial.m"; include "secstore.m"; secstore := load Secstore Secstore->PATH; Maxfilesize: con 128*1024; # default init: fn(); privacy: fn(): int; cansecstore: fn(addr: string, user: string): int; mkseckey: fn(pass: string): array of byte; dial: fn(addr: string): ref Dial->Connection; auth: fn(conn: ref Dial->Connection, user: string, seckey: array of byte): (string, string); connect: fn(addr: string, user: string, seckey: array of byte): (ref Dial->Connection, string, string); sendpin: fn(conn: ref Dial->Connection, pin: string): int; files: fn(conn: ref Dial->Connection): list of (string, int, string, string, array of byte); getfile: fn(conn: ref Dial->Connection, name: string, maxsize: int): array of byte; putfile: fn(conn: ref Dial->Connection, name: string, data: array of byte): int; remove: fn(conn: ref Dial->Connection, file: string): int; bye: fn(conn: ref Dial->Connection); mkfilekey: fn(pass: string): array of byte; decrypt: fn(data: array of byte, filekey: array of byte): array of byte; encrypt: fn(data: array of byte, filekey: array of byte): array of byte; erasekey: fn(key: array of byte); lines: fn(file: array of byte): list of array of byte; Secstore establishes a secure authenticated connection with aPlan 9 secstore service (or equivalent, such as Plan 9 fromUser Space), that can then be used to fetch and decrypt datafiles, such as the factotum file containing the initial keysfor an instance of factotum(4). The module's functions holdthe file descriptors for the connection in a Dial->Connectionvalue, as returned by dial(2). The addr parameter that givesthe network address of the secstore service is also asdefined in dial(2). A nil value defaults to net!$auth!sec‐store, for translation in the usual way by cs(8). Init must be called before invoking any other operation ofthe module. Privacy ensures the memory of the calling process cannot beread, for instance by prog(3). It returns zero on successand a negative value on failure. Cansecstore returns true if a connection can be made to asecstore at network address addr, and the given user has asecstore account; it returns false otherwise. Users authenticate themselves to the service using a secretkey and a special protocol that does not reveal the keyitself to the remote service. The textual secret (eg, pass‐word or pass phrase) is not used directly by the followingfunctions, but only after transformation by mkseckey, whichhashes it into an array of bytes. That is the key parameterto the functions. Dial dials the secstore at network address addr (as definedby dial(2)) and returns a reference to the resultingDial->Connection. It returns nil on an error and sets theerror string. Auth authenticates a fresh connection as belonging to a givenuser of the service. The parameter conn refers to theDial->Connection value representing the connection. Usernames a user registered with the service. The parameterseckey is the result of applying mkseckey to the user'ssecret. Auth returns a tuple (srvname, diag). Srvname isthe service name configured in the remote host (often simplysecstore). On an error, srvname is nil, and diag is a diag‐nostic. If the remote service has been configured to demandextra authentication data, then diag contains a demand forit. Currently the only such value is `needpin'; call sendpinto provide it to the connection. If sendpin succeeds, itreturns zero, and conn can be used normally; on error, send‐pin returns -1 and the connection cannot be used. Connect combines the actions of dial and auth: dials the sec‐store at addr, and mutually authenticates the server and thegiven user using the user's secret key for that service. Itreturns a tuple (conn, srvname, diag), where each componentis as described for dial and auth above. On an error, connis nil, and diag contains a diagnostic. Getfile retrieves the file name from the secure store, andreturns its contents as an array of bytes. Maxsize gives thelargest acceptable file size; if the value is zero or nega‐tive, a large value is used by default. The files stored onthe service are separately encrypted under the user's secretkey. Mkfilekey takes a textual secret key and returns a hashof it as an array of bytes, suitable for use as the filekeyparameter in subsequent calls to decrypt. (The filekey isnot the same value as the seckey used for initial authentica‐tion, although the secret text is the same.) Putfile writes data under file name to the secure store,overwriting a possibly existing file by that name. Datashould already be encrypted. The caller can arrange this bycalling encrypt. Putfile returns 0 on success and a negativevalue on error. Remove deletes the given file from the server. It returns 0on success and a negative value on error. Decrypt decrypts the data previously fetched from a file onthe secure store. It uses the filekey produced by mkfilekeyto decrypt the data in place (ie, modifying the contents ofdata) and returns a slice of data that excludes any headersand trailers in the encoding. It returns nil if the filecould not be decrypted (usually because the key value is notactually the encryption key). Encrypt does the opposite of decrypt. Given plain data andfilekey produced by mkfilekey, it returns an encrypted ver‐sion of data, including headers and trailers. This data issuitable for writing to the secure store with putfile. Erasekey clears the bytes of key to zero; it should be calledon every value produced by mkfilekey and mkseckey, after use,but can also be used on the data arrays returned by getfileand decrypt. Lines returns a list of slices of file, representing eachline of file in turn (including newline). Factotum(4) forinstance requires keys to be written to its control file oneat a time. Bye closes the connection to the secstore. == source/appl/lib/secstore.b == diagnosticsAs well as returning the error values described above, func‐tions set the system error string. == see ALSOcrypt(1), secstore(1), factotum(2), factotum(4)
= secstore: fetch data from Plan 9's secure storage service
include "dial.m";
include "secstore.m";
secstore := load Secstore Secstore->PATH;
Maxfilesize: con 128*1024; # default
init: fn();
privacy: fn(): int;
cansecstore: fn(addr: string, user: string): int;
mkseckey: fn(pass: string): array of byte;
dial: fn(addr: string): ref Dial->Connection;
auth: fn(conn: ref Dial->Connection, user: string, seckey: array of byte):
(string, string);
connect: fn(addr: string, user: string, seckey: array of byte):
(ref Dial->Connection, string, string);
sendpin: fn(conn: ref Dial->Connection, pin: string): int;
files: fn(conn: ref Dial->Connection):
list of (string, int, string, string, array of byte);
getfile: fn(conn: ref Dial->Connection, name: string,
maxsize: int): array of byte;
putfile: fn(conn: ref Dial->Connection, name: string, data: array of byte): int;
remove: fn(conn: ref Dial->Connection, file: string): int;
bye: fn(conn: ref Dial->Connection);
mkfilekey: fn(pass: string): array of byte;
decrypt: fn(data: array of byte, filekey: array of byte): array of byte;
encrypt: fn(data: array of byte, filekey: array of byte): array of byte;
erasekey: fn(key: array of byte);
lines: fn(file: array of byte): list of array of byte;
Secstore establishes a secure authenticated connection with a
Plan 9 secstore service (or equivalent, such as Plan 9 from
User Space), that can then be used to fetch and decrypt data
files, such as the factotum file containing the initial keys
for an instance of factotum(4). The module's functions hold
the file descriptors for the connection in a Dial->Connection
value, as returned by dial(2). The addr parameter that gives
the network address of the secstore service is also as
defined in dial(2). A nil value defaults to net!$auth!sec‐
store, for translation in the usual way by cs(8).
Init must be called before invoking any other operation of
the module.
Privacy ensures the memory of the calling process cannot be
read, for instance by prog(3). It returns zero on success
and a negative value on failure.
Cansecstore returns true if a connection can be made to a
secstore at network address addr, and the given user has a
secstore account; it returns false otherwise.
Users authenticate themselves to the service using a secret
key and a special protocol that does not reveal the key
itself to the remote service. The textual secret (eg, pass‐
word or pass phrase) is not used directly by the following
functions, but only after transformation by mkseckey, which
hashes it into an array of bytes. That is the key parameter
to the functions.
Dial dials the secstore at network address addr (as defined
by dial(2)) and returns a reference to the resulting
Dial->Connection. It returns nil on an error and sets the
error string.
Auth authenticates a fresh connection as belonging to a given
user of the service. The parameter conn refers to the
Dial->Connection value representing the connection. User
names a user registered with the service. The parameter
seckey is the result of applying mkseckey to the user's
secret. Auth returns a tuple (srvname, diag). Srvname is
the service name configured in the remote host (often simply
secstore). On an error, srvname is nil, and diag is a diag‐
nostic. If the remote service has been configured to demand
extra authentication data, then diag contains a demand for
it. Currently the only such value is `needpin'; call sendpin
to provide it to the connection. If sendpin succeeds, it
returns zero, and conn can be used normally; on error, send‐
pin returns -1 and the connection cannot be used.
Connect combines the actions of dial and auth: dials the sec‐
store at addr, and mutually authenticates the server and the
given user using the user's secret key for that service. It
returns a tuple (conn, srvname, diag), where each component
is as described for dial and auth above. On an error, conn
is nil, and diag contains a diagnostic.
Getfile retrieves the file name from the secure store, and
returns its contents as an array of bytes. Maxsize gives the
largest acceptable file size; if the value is zero or nega‐
tive, a large value is used by default. The files stored on
the service are separately encrypted under the user's secret
key. Mkfilekey takes a textual secret key and returns a hash
of it as an array of bytes, suitable for use as the filekey
parameter in subsequent calls to decrypt. (The filekey is
not the same value as the seckey used for initial authentica‐
tion, although the secret text is the same.)
Putfile writes data under file name to the secure store,
overwriting a possibly existing file by that name. Data
should already be encrypted. The caller can arrange this by
calling encrypt. Putfile returns 0 on success and a negative
value on error.
Remove deletes the given file from the server. It returns 0
on success and a negative value on error.
Decrypt decrypts the data previously fetched from a file on
the secure store. It uses the filekey produced by mkfilekey
to decrypt the data in place (ie, modifying the contents of
data) and returns a slice of data that excludes any headers
and trailers in the encoding. It returns nil if the file
could not be decrypted (usually because the key value is not
actually the encryption key).
Encrypt does the opposite of decrypt. Given plain data and
filekey produced by mkfilekey, it returns an encrypted ver‐
sion of data, including headers and trailers. This data is
suitable for writing to the secure store with putfile.
Erasekey clears the bytes of key to zero; it should be called
on every value produced by mkfilekey and mkseckey, after use,
but can also be used on the data arrays returned by getfile
and decrypt.
Lines returns a list of slices of file, representing each
line of file in turn (including newline). Factotum(4) for
instance requires keys to be written to its control file one
at a time.
Bye closes the connection to the secstore.
== source
/appl/lib/secstore.b
== diagnostics
As well as returning the error values described above, func‐
tions set the system error string.
== see ALSO
crypt(1), secstore(1), factotum(2), factotum(4)